Setting up a multiplayer project
This page contains an overview of the most basic and common things you need when setting up a multiplayer project. In terms of what you require in your project, these are:
A Network Manager
A user interface (for players to find and join games)
Networked Player Prefabs (for players to control)
Scripts A piece of code that allows you to create your own Components, trigger game events, modify Component properties over time and respond to user input in any way you like. More info
See in Glossary and GameObjects The fundamental object in Unity scenes, which can represent characters, props, scenery, cameras, waypoints, and more. A GameObject’s functionality is defined by the Components attached to it. More info
See in Glossary which are multiplayer-aware
There are variations on this list; for example, in a multiplayer chess game, or a real-time strategy (RTS) game, you don’t need a visible GameObject to represent the player. However, you might still want an invisible empty GameObject to represent the player, and attach scripts to it which relate to what the player is able to do.
This introductory page contains a brief description of each of the items listed above. However, each section links to more detailed documentation, which you need to continue reading to fully understand them.
There are also some important concepts that you need to understand and make choices about when building your game. These concepts can broadly be summarised as:
The relationship between a client, a server, and a host
The idea of authority over GameObjects and actions
The Network Manager
The Network Manager is responsible for managing the networking aspects of your multiplayer game. You should have one (and only one) Network Manager active in your Scene A Scene contains the environments and menus of your game. Think of each unique Scene file as a unique level. In each Scene, you place your environments, obstacles, and decorations, essentially designing and building your game in pieces. More info
See in Glossary at a time.
The Network Manager Component
Unity’s built-in Network Manager component wraps up all of the features for managing your multiplayer game into one single component. If you have custom requirements which aren’t covered by this component, you can write your own network manager in script instead of using this component. If you’re just starting out with multiplayer games, you should use this component.
To learn more, see documentation on the Network Manager A Networking component that manages the network state of a project. More info
See in Glossary .
A user interface for players to find and join games
Almost every multiplayer game provides players with a way to discover, create, and join individual game “instances” (also known as “matches”). This part of the game is commonly known as the “lobby”, and sometimes has extra features like chat.
A typical multiplayer game lobby, allowing players to find, create and join games, as seen in the TANKS networking demo, available on the Asset Store.
Unity has an extremely basic built-in version of such an interface, called the NetworkManagerHUD A Networking component that creates a UI menu that allows you to control the network state of your game using your Network Manager. More info
See in Glossary . It can be extremely useful in the early stages of creating your game, because it allows you to easily create matches and test your game without needing to implement your own UI (User Interface) Allows a user to interact with your application. Unity currently supports three UI systems. More info
See in Glossary . However, it is very basic in both functionality and visual design, so you should replace this with your own UI before you finish your project.
Unity’s built-in Network Manager HUD, shown in MatchMaker mode.
To learn more, see documentation on the Network Manager HUD.
Networked player GameObjects
Most multiplayer games feature some kind of object that a player can control, like a character, a car, or something else. Some multiplayer games don’t feature a single visible “ player object A High Level API (HPAPI) object that represents the player on the server and has the ability to run commands (which are secure client-to-server remote procedure calls) from the player’s client. More info
See in Glossary ” but instead allow a player to control many units or items, like in chess or real-time strategy games. Others don’t even feature specific objects at all, like a shared-canvas painting game. In all of these situations, however, you usually need to create a GameObject that conceptually represents the player in your game. Make this GameObject a Prefab An asset type that allows you to store a GameObject complete with components and properties. The prefab acts as a template from which you can create new object instances in the scene. More info
See in Glossary , and attach all the scripts to it which control what the player can do in your game.
If you are using Unity’s Network Manager component (see The Network Manager, above), assign the Prefab to the Player Prefab field.
The network manager with a “Player Car” prefab assigned to the Player Prefab field.
When the game is running, the Network Manager creates a copy (an “instance”) of your player Prefab for each player that connects to the match.
However — and this is where it can get confusing for people new to multiplayer programming — you need to make sure the scripts on your player Prefab instance are “aware” of whether the player controlling the instance is using the host computer (the computer that is managing the game) or a client computer (a different computer to the one that is managing the game).
This is because both situations will be occurring at the same time.
Multiplayer-aware Scripts
Writing scripts for a multiplayer game is different to writing scripts for a single-player game. This is because when you write a script for a multiplayer game, you need to think about the different contexts that the scripts run in.
For example, the scripts you place on your player Prefab should allow the “owner” of that player instance to control it, but it should not allow other people to control it.
You need to think about whether the server or the client has authority over what the script does. Sometimes, you want the script to run on both the server and the clients. Other times, you only want the script to run on the server, and you only want the clients to replicate how the GameObjects are moving (for example, in a game in which players pick up collectible GameObjects, the script should only run on the server so that the server can be the authority on the number of GameObjects collected).
Depending on what your script does, you need to decide which parts of your script should be active in which situations.
For player GameObjects, each person usually has active control over their own player instance. This means each client has local authority over its own player, and the server accepts what the client tells it about what the player is doing.
For non-player GameObjects, the server usually has authority over what happens (such as whether an item has been collected), and all clients accept what the server tells them about what has happened to that GameObject.
Turn-based Multiplayer Games in Unity3D using UNet
Note: This article uses unity3d multiplayer networking concepts, learn more here “Unity-Multiplayer Networking”.
After going through the internet like crazy in search of tutorials for creating turn-based multiplayer games in Unity3D, I have arrived at a decision to do it on my own and help my fellow creators to end this struggle.
This is what you will need:
- Network Manager
- Network Player
- Player Controller
NetworkManager
For playing multiplayer games, you need a server to host the games which will also watch over the connected players to maintain their states as the game progresses. First of all, the server will create a match and broadcast the match ID to all the players in the network. The players then are connected to the game by joining the match using the match ID.
A Network Manager game object is responsible for these tasks. All the connected players in the match are stored in a list. AlterTurns() method ends the current player’s turn and starts the next player’s turn by changing the active player index iActivePlayer . Similarly, it updates the active player score, when a player score update is requested by the client.
NetworkPlayer
A Network Player game object is spawned by unity when a player joins the match. The player hosting or creating a match acts as a server. While the player joining the match is a client. All the player in the network are kept in sync with the server.
The synchronization between the clients and the server validates the states of game objects across the network for each player in the match.
The idea is to keep the current turn timer, active player index and scores in sync between the players and use network manager to alternate turns and update scores. The objects on client players are a copy of objects on the server. So, to make any changes in the game state, a client must let the server know about the changes and any changes in the game state at server must be notified to the other clients.
I bet we really need something complex and sophisticated here like a blockchain. 😀
Well, not really. The way this is done by making “RPC” calls and sending network “commands”.
PlayerController
A Player Controller game object is responsible to send player actions like shooting or jumping to the server. You can use this to spawn and unspawn player/objects on the network using TurnStart() and TurnEnd() methods.
Настройка многопользовательского проекта
Эта страница содержит обзор самых основных и распространенных вещей, которые вам понадобятся при настройке многопользовательского проекта. С точки зрения того, что вам нужно в вашем проекте, это:
Менеджер сети
пользовательский интерфейс (для того, чтобы игроки могли находить игры и присоединяться к ним)
Сетевые префабы игроков (для управления игроками)
Скрипты Кусок кода, позволяющий создавать собственные компоненты, запускать игровые события, изменять свойства компонентов. со временем и реагировать на пользовательский ввод любым удобным для вас способом. Подробнее
См. в Словарь и GameObjects Основной объект в сценах Unity, который может представлять персонажей, реквизит, декорации, камеры, путевые точки и многое другое. Функциональность GameObject определяется прикрепленными к нему компонентами. Подробнее
См. Словарь , которые поддерживают мультиплеер
В этом списке есть варианты; например, в многопользовательской игре в шахматы или в стратегии в реальном времени (RTS) вам не нужен видимый GameObject для представления игрока. Однако вы все равно можете захотеть, чтобы невидимый пустой GameObject представлял игрока и прикреплял к нему скрипты, относящиеся к тому, что игрок может делать.
Эта вводная страница содержит краткое описание каждого из перечисленных выше элементов. Однако каждый раздел связан с более подробной документацией, которую необходимо продолжить, чтобы полностью понять ее.
Есть также несколько важных концепций, которые необходимо понимать и принимать во внимание при создании игры. Эти концепции можно обобщить следующим образом:
- Отношения между клиентом, сервером и хостом
- Идея власти над игровыми объектами и действиями
Чтобы узнать об этих концепциях, см. документацию по концепциям сетевых систем.
Сетевой менеджер
Сетевой менеджер отвечает за управление сетевыми аспектами многопользовательской игры. У вас должен быть активен один (и только один) Network Manager в вашей Сцене Сцена содержит окружение и меню вашей игры. Думайте о каждом уникальном файле сцены как об уникальном уровне. В каждой сцене вы размещаете свое окружение, препятствия и декорации, по сути проектируя и создавая свою игру по частям. Подробнее
Просмотреть в Словарь за раз.
Компонент диспетчера сети
Встроенный в Unity компонент Network Manager объединяет все функции управления многопользовательской игрой в одном компоненте. Если у вас есть особые требования, которые не охватываются этим компонентом, вы можете написать свой собственный сетевой менеджер в скрипте вместо использования этого компонента. Если вы только начинаете играть в многопользовательские игры, вам следует использовать этот компонент.
Дополнительные сведения см. в документации по Диспетчеру сети Сетевой компонент, управляет сетевым состоянием проекта. Подробнее
См. в Словарь .
Пользовательский интерфейс, позволяющий игрокам находить игры и присоединяться к ним
Почти в каждой многопользовательской игре игроки могут находить, создавать и присоединяться к отдельным игровым «экземплярам» (также называемым «матчами»). Эта часть игры широко известна как «лобби» и иногда имеет дополнительные функции, такие как чат.
Типичное многопользовательское игровое лобби, позволяющее игрокам находить, создавать и присоединяться к играм, как показано в демонстрационной версии сети TANKS, доступной в Asset Store.
В Unity есть чрезвычайно простая встроенная версия такого интерфейса, которая называется NetworkManagerHUD Сетевой компонент, создающий пользовательский интерфейс. меню, которое позволяет вам управлять сетевым состоянием вашей игры с помощью Network Manager. Подробнее
См. в Словарь . Это может быть чрезвычайно полезно на ранних этапах создания игры, поскольку позволяет легко создавать матчи и тестировать игру без необходимости реализовывать собственный пользовательский интерфейс (Пользовательский интерфейс) Позволяет пользователю взаимодействовать с вашим приложением. Подробнее
См. в Словарь . Однако он очень прост как по функциональности, так и по визуальному дизайну, поэтому вам следует заменить его собственным пользовательским интерфейсом, прежде чем вы закончите свой проект.
Встроенный HUD Network Manager в Unity, показанный в режиме MatchMaker.
Чтобы узнать больше, см. документацию по интерфейсу Network Manager.
Игровые объекты сетевого игрока
В большинстве многопользовательских игр есть объект, которым игрок может управлять, например персонаж, машина или что-то еще. В некоторых многопользовательских играх отсутствует один видимый « объект игрока объект API высокого уровня (HPAPI), представляющий игрока на server и имеет возможность запускать команды (которые представляют собой безопасные удаленные вызовы процедур между клиентом и сервером) из клиента проигрывателя. Подробнее
См. в Словарь », но вместо этого разрешить игроку управлять множество юнитов или предметов, как в шахматах или стратегических играх в реальном времени. В других даже нет конкретных объектов, например, в игре с рисованием на общем холсте. Однако во всех этих ситуациях вам обычно необходимо создать GameObject, который концептуально представляет игрока в вашей игре. Сделайте этот GameObject Prefab типом актива, который позволяет хранить GameObject вместе с компонентами и свойствами. Префаб действует как шаблон, из которого вы можете создавать новые экземпляры объектов на сцене. Подробнее
Посмотрите в Словарь и прикрепите к нему все скрипты, которые контролируют то, что делает плеер. можно сделать в вашей игре.
Если вы используете компонент Unity Network Manager (см. Network Manager выше), назначьте Prefab в поле Player Prefab.
Сетевой менеджер с префабом Player Car, назначенным на поле Player Prefab
Когда игра запущена, Network Manager создает копию («экземпляр») вашего префаба игрока для каждого игрока, который подключается к матчу.
Однако — и это может сбить с толку людей, плохо знакомых с многопользовательским программированием, — вам необходимо убедиться, что скрипты в экземпляре Prefab вашего проигрывателя «осведомлены» о том, использует ли игрок, управляющий экземпляром, хост компьютер (компьютер, который управляет игрой) или клиентский компьютер (компьютер, отличный от того, который управляет игрой).
Это связано с тем, что обе ситуации будут происходить одновременно.
Скрипты для многопользовательской игры
Написание сценариев для многопользовательской игры отличается от написания сценариев для однопользовательской игры. Это связано с тем, что при написании сценария для многопользовательской игры необходимо учитывать различные контексты, в которых выполняются сценарии. Чтобы узнать об обсуждаемых здесь сетевых концепциях, см. документацию по концепциям сетевых систем. .
Например, скрипты, которые вы размещаете в своем префабе проигрывателя, должны позволять «владельцу» этого экземпляра проигрывателя управлять им, но не должны позволять другим людям управлять им.
Вам нужно подумать о том, кто имеет полномочия на то, что делает скрипт, сервер или клиент. Иногда вам нужно, чтобы сценарий выполнялся как на сервере, так и на клиентах. В других случаях вы хотите, чтобы сценарий выполнялся только на сервере, и вы хотите, чтобы клиенты воспроизводили только то, как перемещаются игровые объекты (например, в игре, в которой игроки собирают коллекционные игровые объекты, сценарий должен выполняться только на сервере). чтобы сервер мог быть авторитетом в отношении количества собранных игровых объектов).
В зависимости от того, что делает ваш скрипт, вам нужно решить, какие части вашего скрипта должны быть активны в каких ситуациях.
Что касается игровых объектов GameObject, каждый человек обычно имеет активный контроль над своим собственным экземпляром игрока. Это означает, что каждый клиент имеет локальные полномочия по отношению к своему проигрывателю, и сервер принимает то, что клиент сообщает ему о том, что делает проигрыватель.
Для неигровых игровых объектов сервер обычно имеет полномочия на то, что происходит (например, был ли собран предмет), и все клиенты принимают то, что сервер сообщает им о том, что произошло с этим игровым объектом.
Основы многопользовательской игры на Unity3D

Я, как и многие из вас, большой поклонник многопользовательских игр. В них меня прельщает в основном дух соревнования и возможность приобретать улучшения, накапливая достижения. Да и сама идея выхода в свет все большего количества игр данного типа побуждает к действию.
С недавнего времени я и сам взялся за разработку собственного проекта. И поскольку на Хабрахабре статей на эту тематику не нашел – решил поделиться своим опытом написания многопользовательской игры на движке Unity3D. Также хочу рассказать о компонентах Network и NetworkView, атрибуте RPC и встроенных методах-ивентах. В конце статьи подан пример игры и, разумеется, сам проект для Unity. Итак…
Класс Network
Данный класс нужен для организации соединения «клиент-сервер». Основные функции: создание сервера, подключение к серверу, создание сетевого экземпляра префаба.
Основные методы:
Network.Connect (string host, int remotePort, string password = «») – выполняет подключение к серверу host с портом remotePort и паролем password. Метод возвращает перечисление NetworkConnectionError.
Network.InitializeServer(int connections, int listenPort, bool useNat) – создает сервер с максимально разрешенным количеством подключений connections; порт входящих подключений listenPort, а также useNat: использовать либо нет NAT . Также возвращает перечисление NetworkConnectionError.
Network.InitializeSecurity() – вызывается перед Network.InitializeServer() для защиты от читерства. Подробности в официальной документации. Не вызывать на клиенте!
Network.Instantiate(Object prefab, Vector3 position, Quaternion rotation, int group) – создает экземпляр префаба prefab в сети в позиции position с поворотом rotation и группой group. Возвращает весь созданный объект, с которым после создания можно выполнить дополнительные действия. Подробности – далее в статье.
Основные свойства:
bool Network.isClient и bool Network.isServer – определяют, является ваша игра сервером либо клиентом. Оба свойства являются false, если не был создан сервер или не было подключения к серверу.
string Network.incomingPassword – свойство задает пароль для входящих подключений.
NetworkPlayer Network.player – возвращает экземпляр локального игрока NetworkPlayer.
NetworkPeerType Network.peerType – возвращает текущее состояние подключения: Disconnected (отключен), Server (запущен как сервер), Client (подключен к серверу), Connecting (попытка, в процессе подключения).
NetworkPlayer[] Network.connections – возвращает всех подключенных игроков. На клиенте возвращает только игрока сервера.
Основные ивенты (для унаследованного от MonoBehaviour):
OnConnectedToServer() – вызывается на клиенте при успешном подключении к серверу.
OnDisconnectedFromServer(NetworkDisconnection info) – вызывается на клиенте при отключении от сервера и на сервере при завершении подключений Network.Disconnect(). В info содержится причина отключения: LostConnection (потеря связи) и Disconnected (при успешном отключении).
OnFailedToConnect(NetworkConnectionError error) — вызывается на клиенте при ошибке подключения. error содержит ошибку типа NetworkConnectionError.
OnNetworkInstantiate(NetworkMessageInfo info) — вызывается на клиенте и сервере, если был создан новый экземпляр методом Network.Instantiate(). Содержит info типа NetworkMessageInfo.
OnPlayerConnected(NetworkPlayer player) — вызывается на сервере при успешном подключении клиента и содержит player типа NetworkPlayer.
OnPlayerDisconnected(NetworkPlayer player) — вызывается на сервере при отключении клиента и содержит player типа NetworkPlayer.
OnServerInitialized() — вызывается на сервере, после того как сервер был успешно создан.
OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info) — важный ивент для синхронизации компонента с сетью. Подробности – далее в статье.
Класс NetwokView
Данный класс существует также и как компонент для Unity, и предназначен он для синхронизации компонентов в сети и для вызова RPC .
Обладает такими свойствами синхронизации NetworkStateSynchronization:
- Off — не выполняет синхронизацию объекта, однако позволяет вызывать удаленные процедуры.
- ReliableDeltaCompressed — выполняет передачу пакетов поочередно и проверяет, доставлен ли пакет (подобно протоколу TCP).
- Unreliable — выполняет быструю отправку пакетов, не гарантируя доставки (подобно протоколу UDP).
Основные методы:
networkView.RPC(string name, RPCMode mode, params object[] args) — вызывает удаленную процедуру name, mode определяет получателей, args – аргументы для передачи процедуре.
networkView.RPC(string name, NetworkPlayer target, params object[] args) – то же, что и предыдущий метод, однако выполняет отправку конкретному игроку NetworkPlayer.
Основные свойства:
bool networkView.isMine – свойство, определяющее, является ли объект локальным. Весьма часто используется для проверки владельца объекта.
Component networkView.observed – компонент, который будет синхронизироваться. Если это скрипт, то он должен содержать метод OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info), упомянутый выше.
NetworkPlayer networkView.owner – свойство, возвращающее владельца объекта.
NetworkStateSynchronization networkView.stateSynchronization — тип синхронизации: Off, ReliableDeltaCompressed, Unreliable.
NetworkViewID networkView.viewID — уникальный идентификатор в сети для NetworkView.
Атрибут RPC
Метод OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
Данный метод используется для синхронизации компонента в сети. Он вызывается всякий раз при получении либо отправке данных по сети.
Вот типы данных, которые могут быть получены/отправлены методом Serialize: bool, char, short, int, float, Quaternion, Vector3, NetworkPlayer, NetworkViewID.
Для проверки, идет ли прием либо передача, используются свойства isReading или isWriting.
Привожу пример использования:
Данный пример не идеален, поскольку при его работе наши объекты будут «дергаться». Чтобы избежать этого, нужно воспользоваться интерполяцией. Подробнее – далее в статье.
Интерполяция

Подробнее о методах оптимизации синхронизации по сети смотрите на сайте разработчиков: Valve Developer Community — Source Multiplayer Networking
Пример многопользовательской игры
Итак, имея представления об основах, можно приниматься за написание небольшой многопользовательской игры. В качестве примеров я использую разные способы применения NetworkView. Вам остается лишь выбрать для себя наиболее удобный способ.
Создаем скрипт ServerSide.cs и пишем туда следующее:
Теперь создаем скрипт клиента ClientSide.cs:
Таким образом, клиентская и серверная логика есть, теперь для нее нужно сделать управление MainMenu.cs:
Управление сетью создано. Далее пишем управление игроком PlayerControls.cs. В данном примере я использую другой способ применения компонента NetworkView:
Знаю, что синхронизация и управление должны находиться раздельно, но для примера я решил объединить их. Как вы заметили, здесь NetworkView создается во время инициализации скрипта. На мой взгляд, это более удобный способ для защиты от возможного «забыл добавить» (разумеется, если не написано RequireComponent( typeof( Rigidbody ))), а также уменьшает в инспекторе количество компонентов на объекте.
К примеру, у меня был случай: когда, на первый взгляд, все было сделано правильно, однако мой скрипт не делал интерполяцию, и все мои действия в синхронизации игнорировал. Так вот ошибкой оказалось то, что Observed был не моим скриптом, а трансформ объекта.
Итак, теперь у нас есть все необходимые скрипты для написания мини-игры.
Создаем пустой объект и назначаем ему скрипты MultiplayerMenu, ServerSide, ClientSide.
Создаем плоскость и немного опускаем.
Создаем префаб игрока (в моем примере это будут шары). Создаем объект «сфера», назначаем ему скрипт PlayerControls и добавляем в префаб. Префаб перетягиваем на ClientSide в поле Player Prefab.
На этом все, компилируем проект (не забывая в настройках игрока включить Run in background) и запускаем несколько раз. В одном из окон жмем сервер, на остальных – клиент, и смотрим на результат.
Ссылка на проект.
*В проекте могут быть логические ошибки, но на суть данной статьи они не влияют.
Всех благодарю за внимание!
Желаю успехов в создании многопользовательских игр!