Мои Уведомления
Привет, !
Мой Аккаунт Мои Финансы Мои Подписки Мои Настройки Выход
Руководство API скрипты
Важно: UNet — это устаревшее решение, а также новая многопользовательская и сетьсистема Unity, которая обеспечивает многопользовательскую игру. игры через компьютерную сеть. Подробнее
См. в Словарь
Решение (Netcode для GameObjects) находится в разработке. Дополнительную информацию и дальнейшие действия см. на веб-сайте Unity Netcode for GameObjects.

В Unity вы обычно «порождаете» (то есть создаете) новые GameObjectsфундаментальные объекты в сценах Unity, которые может представлять персонажей, реквизит, декорации, камеры, путевые точки и многое другое. Функциональность GameObject определяется прикрепленными к нему компонентами. Подробнее
См. в Словарь
с Создать экземпляр(). Однако в многопользовательском API высокого уровнясистема создания многопользовательских возможностей для игр Unity. Он построен поверх нижнего уровня транспортного уровня связи в реальном времени и выполняет многие общие задачи, необходимые для многопользовательских игр. Подробнее
Посмотрите в Словарь
, слово "порождение" означает что-то более конкретное. В авторитетной для сервера модели HLAPI «порождение» GameObject на сервере означает, что GameObject создается на клиентах, подключенных к серверу, и управляется системой создания.

После создания игрового объекта с помощью этой системы обновления состояния отправляются клиентам при каждом изменении игрового объекта на сервере. Когда Unity уничтожает GameObject на сервере, он также уничтожает его и на клиентах. Сервер управляет созданными игровыми объектами наряду со всеми другими сетевыми игровыми объектами, так что, если позже к игре присоединится другой клиент, сервер сможет создать игровые объекты на этом клиенте. Эти порожденные игровые объекты имеют уникальный идентификатор экземпляра сети, называемый «netIdУникальный идентификатор, присваиваемый экземпляру объекта для отслеживания его между сетевыми клиентами и сервер. Подробнее
См. в Словарь
», который одинаков на сервере и клиентах для каждого игрового объекта. . Уникальный идентификатор экземпляра сети используется для маршрутизации сообщений, установленных по сети, к игровым объектам и для идентификации игровых объектов.

Когда сервер порождает GameObject с компонентом Network Identity****, GameObject, созданный на клиенте, имеет такое же «состояние». . Это означает, что он идентичен GameObject на сервере; он имеет такое же преобразование, состояние движения и (если NetworkTransformA Networking компонент, позволяющий синхронизировать перемещения игровых объектов по сети. Подробнее
См. в Словарь
и SyncVars используются) синхронизированные переменные. Поэтому клиентские игровые объекты всегда актуальны, когда их создает Unity. Это позволяет избежать таких проблем, как появление игровых объектов в неправильном начальном местоположении, а затем их повторное появление в правильном положении при поступлении обновления состояния.

Диспетчер сетиКомпонент сети, который управляет сетевым состоянием проекта. Подробнее
См. в Словарь
может создавать и синхронизировать игровые объекты только из зарегистрированных Префабы, поэтому вы должны зарегистрировать определенные префабы GameObject в Network Manager, которые вы хотите иметь возможность создавать во время игры. Диспетчер сети будет принимать только префабы GameObject, к которым прикреплен компонент сетевой идентификации, поэтому вы должны убедиться, что добавили компонент сетевой идентификации в свой префабТип актива, который позволяет хранить GameObject с компонентами и свойствами. Префаб действует как шаблон, из которого вы можете создавать новые экземпляры объектов на сцене. Подробнее
См. Словарь
, прежде чем пытаться зарегистрировать его в Network Manager.

Чтобы зарегистрировать префаб в Network Manager в редакторе, выберите игровой объект Network Manager и в InspectorA Unity окно, в котором отображается информация о текущем выбранном игровом объекте, активе или настройках проекта, что позволяет просматривать и редактировать значения. Дополнительная информация
См. в Словарь
, перейдите к компоненту Network Manager. Нажмите треугольник рядом с Информация о порождении, чтобы открыть настройки, затем в разделе Зарегистрированные порождаемые префабы нажмите кнопку с плюсом (+). Перетащите префабы в пустое поле, чтобы добавить их в список.

Инспектор Network Manager с развернутой раскладкой Spawn Info*, отображающей три назначенных префаба в разделе Registered Spawnable Prefabs.
Инспектор Network Manager с развернутой раскладкой Spawn Info*, отображающей три назначенных префаба в разделе Registered Spawnable Prefabs.

Создание без Network Manager

Для более продвинутых пользователей может потребоваться регистрация префабов и создание игровых объектов без использования компонента NetworkManager.

Чтобы создавать игровые объекты без использования Network Manager, вы можете выполнить регистрацию Prefab самостоятельно с помощью скрипта. Используйте метод ClientScene.RegisterPrefab, чтобы зарегистрировать префабы в Network Manager.

Пример: MyNetworkManager

using UnityEngine; using UnityEngine.Networking; public class MyNetworkManager : MonoBehaviour { public GameObject treePrefab; NetworkClient myClient; // Create a client and connect to the server port public void ClientConnect() { ClientScene.RegisterPrefab(treePrefab); myClient = new NetworkClient(); myClient.RegisterHandler(MsgType.Connect, OnClientConnect); myClient.Connect("127.0.0.1", 4444); } void OnClientConnect(NetworkMessage msg) { Debug.Log("Connected to server: " + msg.conn); } }

В этом примере вы создаете пустой GameObject для работы в качестве Network Manager, затем создаете и прикрепляете к этому GameObject сценарий MyNetworkManager (см. выше). Создайте Prefab, к которому прикреплен компонент Network Identity, и перетащите его в слот treePrefab компонента MyNetworkManager в Инспекторе. Это гарантирует, что когда сервер порождает дерево GameObject, он также создает такой же тип GameObject на клиентах.

Регистрация префабов гарантирует, что актив загружается вместе с СценойСцена содержит окружение и меню вашей игры. Думайте о каждом уникальном файле сцены как об уникальном уровне. В каждой сцене вы размещаете свое окружение, препятствия и декорации, по сути проектируя и создавая свою игру по частям. Подробнее
См. в Словарь
, чтобы не было задержки или времени загрузки при создании Актив.

Однако для работы скрипта необходимо также добавить код для сервера. Добавьте это в скрипт MyNetworkManager:

public void ServerListen() { NetworkServer.RegisterHandler(MsgType.Connect, OnServerConnect); NetworkServer.RegisterHandler(MsgType.Ready, OnClientReady); if (NetworkServer.Listen(4444)) Debug.Log("Server started listening on port 4444"); } // When client is ready spawn a few trees void OnClientReady(NetworkMessage msg) { Debug.Log("Client is ready to start: " + msg.conn); NetworkServer.SetClientReady(msg.conn); SpawnTrees(); } void SpawnTrees() { int x = 0; for (int i = 0; i < 5; ++i) { var treeGo = Instantiate(treePrefab, new Vector3(x++, 0, 0), Quaternion.identity); NetworkServer.Spawn(treeGo); } } void OnServerConnect(NetworkMessage msg) { Debug.Log("New client connected: " + msg.conn); }

Серверу не нужно ничего регистрировать, так как он знает, какой игровой объект создается (и идентификатор объекта отправляется в сообщении о создании). Клиент должен иметь возможность искать GameObject, поэтому он должен быть зарегистрирован на клиенте.

При написании собственного сетевого менеджера важно сделать клиент готовым к получению обновлений состояния перед вызовом команды spawn на сервере, иначе они не будут отправлены. Если вы используете встроенный в Unity компонент Network Manager, это происходит автоматически.

Для более сложных задач, таких как пулы объектов или динамически создаваемые активы, можно использовать метод ClientScene.RegisterSpawnHandler, который позволяет выполнять обратный вызов. функции, которые необходимо зарегистрировать для порождения на стороне клиента. Пример этого см. в документации по Пользовательским функциям создания.

Если GameObject имеет сетевое состояние, такое как синхронизированные переменные, то это состояние синхронизируется с сообщением о появлении. В следующем примере этот скрипт прикреплен к префабу дерева:

using UnityEngine; using UnityEngine.Networking; class Tree : NetworkBehaviour { [SyncVar] public int numLeaves; public override void OnStartClient() { Debug.Log("Tree spawned with leaf count " + numLeaves); } }

С помощью этого скрипта вы можете изменить переменную numLeaves и изменить функцию SpawnTrees, чтобы она точно отражалась на клиент:

void SpawnTrees() { int x = 0; for (int i = 0; i < 5; ++i) { var treeGo = Instantiate(treePrefab, new Vector3(x++, 0, 0), Quaternion.identity); var tree = treeGo.GetComponent(); tree.numLeaves = Random.Range(10,200); Debug.Log("Spawning leaf with leaf count " + tree.numLeaves); NetworkServer.Spawn(treeGo); } }

Присоедините скрипт Tree к скрипту treePrefab, созданному ранее, чтобы увидеть его в действии.

Ограничения

  • A NetworkIdentityСетевой компонент, который позволяет назначать идентификатор вашему игровому объекту, чтобы сеть могла его распознать. в качестве игрового объекта локального игрока или игрового объекта только для сервера. Подробнее
    См. в Словарь
    должен находиться в корневом игровом объекте создаваемого префаба. Без этого Network Manager не сможет зарегистрировать Prefab.

  • NetworkBehaviour скриптыЧасть кода, позволяющая создавать собственные компоненты, запускать игровые события, изменять компоненты свойства с течением времени и реагировать на пользовательский ввод любым удобным для вас способом. Подробнее
    See in Словарь
    должен находиться в том же GameObject, что и NetworkIdentity, а не в дочернем Игровые объекты

Последовательность создания GameObject

Действительный поток внутренних операций, происходящих при создании GameObjects, следующий:

  • Сборный компонент с сетевым идентификатором зарегистрирован как порождаемый.

  • Игровой объект создается из префаба на сервере.

  • Код игры задает начальные значения для экземпляра (обратите внимание, что силы трехмерной физики, примененные здесь, не вступают в силу немедленно).

  • NetworkServer.Spawn() вызывается вместе с экземпляром.

  • Состояние SyncVars в экземпляре на сервере собирается путем вызова OnSerialize() в Network Behaviour компоненты.

  • Подключенным клиентам отправляется сетевое сообщение типа MsgType.ObjectSpawn, содержащее данные SyncVar.

  • OnStartServer() вызывается для экземпляра на сервере, и для isServer установлено значение true

  • Клиенты получают сообщение ObjectSpawn и создают новый экземпляр из зарегистрированного префаба.

  • Данные SyncVar применяются к новому экземпляру на клиенте путем вызова OnDeserialize() для компонентов Network Behavior.

  • OnStartClient() вызывается для экземпляра на каждом клиенте, а isClient устанавливается в true

  • По ходу игры изменения значений SyncVar автоматически синхронизируются с клиентами. Это продолжается до конца игры.

  • NetworkServer.Destroy() вызывается для экземпляра на сервере.

  • Клиентам отправляется сетевое сообщение типа MsgType.ObjectDestroy.

  • OnNetworkDestroy() вызывается для экземпляра на клиентах, затем экземпляр уничтожается.

Игровые объекты

Игровые объекты GameObject в HLAPI работают несколько иначе, чем неигровые игровые объекты. Процесс создания GameObjects игрока с помощью Network Manager:

  • Prefab с NetworkIdentity регистрируется как PlayerPrefab

  • Клиент подключается к серверу

  • Клиент вызывает AddPlayer(), на сервер отправляется сетевое сообщение типа MsgType.AddPlayer р>

  • Сервер получает сообщение и вызывает NetworkManager.OnServerAddPlayer()

  • GameObject создается из PlayerPrefab на сервере

  • NetworkManager.AddPlayerForConnection() вызывается с новым экземпляром проигрывателя на сервере

  • Экземпляр проигрывателя создан — вам не нужно вызывать NetworkServer.Spawn() для экземпляра проигрывателя. Сообщение о порождении отправляется всем клиентам, как при обычном порождении.

  • Сетевое сообщение типа MsgType.Owner отправляется клиенту, добавившему игрока (только этому клиенту!)

  • Исходный клиент получает сетевое сообщение

  • OnStartLocalPlayer() вызывается для экземпляра проигрывателя в исходном клиенте, и для isLocalPlayer установлено значение true

Обратите внимание, что OnStartLocalPlayer() вызывается после OnStartClient(), потому что это происходит только тогда, когда сообщение о владении поступает из сервер после создания игрового объекта игрока, поэтому isLocalPlayer не задан в OnStartClient().

Поскольку OnStartLocalPlayer вызывается только для GameObject локального игрока клиента, это хорошее место для выполнения инициализации, которую следует выполнять только для локального игрока. Это может включать в себя включение обработки ввода и включение камерыкомпонента, который создает изображение определенной точки обзора в вашей сцене. Вывод либо рисуется на экране, либо фиксируется в виде текстуры. Подробнее
См. в Словарь
отслеживание GameObject игрока.

Создание игровых объектов с правами клиента

Чтобы создать GameObjects и назначить права доступа к этим GameObjects конкретному клиенту, используйте NetworkServer.SpawnWithClientAuthority, который принимает в качестве аргумента NetworkConnection клиента, которому необходимо сделать полномочия.

Для этих игровых объектов свойство hasAuthority имеет значение true на клиенте с полномочиями, а OnStartAuthority() вызывается на клиент с полномочиями. Этот клиент может выдавать команды для этого GameObject. На других клиентах (и на хосте) hasAuthority имеет значение false.

Объекты, созданные с правами клиента, должны иметь LocalPlayerAuthority, установленный в их NetworkIdentity.

Например, приведенный выше пример порождения дерева можно изменить, чтобы дерево имело такие полномочия клиента (обратите внимание, что теперь нам нужно передать игровой объект NetworkConnection для подключения клиента-владельца):

void SpawnTrees(NetworkConnection conn) { int x = 0; for (int i = 0; i < 5; ++i) { var treeGo = Instantiate(treePrefab, new Vector3(x++, 0, 0), Quaternion.identity); var tree = treeGo.GetComponent(); tree.numLeaves = Random.Range(10,200); Debug.Log("Spawning leaf with leaf count " + tree.numLeaves); NetworkServer.SpawnWithClientAuthority(treeGo, conn); } }

Теперь можно изменить скрипт Tree для отправки команды на сервер:

public override void OnStartAuthority() { CmdMessageFromTree("Tree with " + numLeaves + " reporting in"); } [Command] void CmdMessageFromTree(string msg) { Debug.Log("Client sent a tree message: " + msg); }

Обратите внимание, что вы не можете просто добавить вызов CmdMessageFromTree в OnStartClient, потому что в этот момент полномочия не были еще не установлено, поэтому вызов не будет выполнен.

Вы можете отблагодарить автора, за перевод документации на русский язык. ₽ Спасибо
Руководство Unity 2021.3