Інтеграція Mirror для мультиплеєра мобільних ігор (Unity)
Mirror—open-source мережевий фреймворк для Unity, спадкоємець застарілого UNET. На відміну від Photon, Mirror не прив'язаний до хмари: транспорт підключається окремо (kcp2k, Telepathy, WebSockets, Steam), сервер можна поднімати на своїй інфраструктурі. Для мобільних проектів це означає повний контроль над затримкою, трафіком та вартістю хостингу—але й повну відповідальність за інфраструктуру.
NetworkManager та життєвий цикл
NetworkManager—точка входу. Переопредитируйте тільки необхідне:
public class GameNetworkManager : NetworkManager
{
public override void OnServerAddPlayer(NetworkConnectionToClient conn)
{
var startPos = GetStartPosition();
var player = Instantiate(playerPrefab, startPos.position, startPos.rotation);
NetworkServer.AddPlayerForConnection(conn, player);
}
public override void OnClientDisconnect()
{
base.OnClientDisconnect();
// Reconnect логіка для мобільного
StartCoroutine(TryReconnect());
}
}
NetworkManager.singleton—статичний доступ до інстансу. Критична помилка: створення кількох NetworkManager у сцені. Mirror видає попередження, але не краш—непередбачувана поведінка пізніше.
SyncVar, SyncList та Commands
[SyncVar] синхронізує змінну з сервера на всі клієнти автоматично при зміні:
public class PlayerHealth : NetworkBehaviour
{
[SyncVar(hook = nameof(OnHealthChanged))]
public int health = 100;
void OnHealthChanged(int oldVal, int newVal)
{
healthBar.fillAmount = newVal / 100f;
}
[Command]
public void CmdTakeDamage(int amount)
{
// Виконується тільки на сервері
health = Mathf.Max(0, health - amount);
}
}
[Command]—клієнт викликає метод на сервері. [ClientRpc]—сервер викликає на всіх клієнтах. [TargetRpc]—на конкретному клієнті. Ця тройка основна перед усім іншим.
SyncList<T> синхронізує колекції: інвентар, очередь баффів, список вбивств. Callback-и OnChange спрацьовують при будь-якій зміні списку.
Вибір транспорту для мобільного
| Транспорт | Протокол | Мобільний |
|---|---|---|
| kcp2k | UDP-based | Рекомендується, низька затримка |
| Telepathy | TCP | Надійний, вища затримка |
| WebSockets (Mirror) | TCP/WS | Потрібен для WebGL, не оптимален native |
| Ignorance | UDP (ENet) | Хороша альтернатива kcp2k |
Для мобільного нативного—kcp2k або Ignorance. kcp2k вбудований у Mirror з версії 50+. Налаштування: NoDelay = true, Interval = 10ms, FastResend = 2.
Headless-сервер та інфраструктура
Mirror-сервер—той же Unity білд з флагом -batchmode -nographics. Для мобільної гри з постійними матчами потрібен виділений сервер: один інстанс Unity обслуговує одну кімнату (action-ігри) або кілька (стратегії з малою кількістю гравців).
Оркестрація: Game Server Hosting (Multiplay) від Unity Gaming Services або самостійно на Kubernetes з автоскейлингом. Для невеликих проектів—VPS на DigitalOcean/Hetzner з управлінням через systemd.
Mirror + Telepathy на TCP за звичайним load balancer. Mirror + kcp2k (UDP)—потрібен UDP passthrough, не всі load balancer'и підтримують.
Типові проблеми при інтеграції
NetworkIdentity не знайден. Префаб не зареєстрований у NetworkManager.spawnPrefabs. Спавн через NetworkServer.Spawn упаде в runtime.
Заплутаність authority. isServer, isClient, isLocalPlayer, hasAuthority—чотири різні булеви. Код в Update() без перевірки isLocalPlayer виконується на всіх клієнтах, включаючи чужих гравців.
Disconnect на мобільному. При уході у фон iOS закриває сокет через ~10 секунд. Mirror не відновлює з'єднання автоматично. Реалізуйте OnApplicationPause → при pauseStatus = false (повернення з фону) → перевірка NetworkClient.isConnected → reconnect.
Графік
Базова Mirror-інтеграція з синхронізацією позицій, health та базовим Command/RPC: 1-2 тижні. Повнофункціональна система з headless-сервером, матчмейкингом, reconnect та мобільною оптимізацією: 1-2 місяці. Вартість розраховується індивідуально.







