Как синхронизировать свойства неигрового GameObject в UNet / Unity5?
Я работаю и изучаю некоторые основы Unity 5, UNET и networking. Я сделал простую 3D игру, где вы идете вокруг и изменить цвета объектов. Но я хочу сделать его многопользовательским сейчас, и у меня много проблем с тем, как отправить изменения по сети, чтобы все игроки могли видеть изменение цвета одного игрока.
часть проблемы заключается в том, что было трудно найти ответ, используя новый сетевой движок UNET. И иногда я сталкиваюсь ... ответы, которые для старого пути.
таким образом, главный вопрос заключается в том, как изменить свойство сетевого неигрового GameObject? Цвет, форма, размер, etc..
вот какой код у меня есть сейчас - и у меня было много разных версий, поэтому я просто опубликую текущий:
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class Player_Paint : NetworkBehaviour {
private int range = 200;
[SerializeField] private Transform camTransform;
private RaycastHit hit;
[SyncVar] private Color objectColor;
[SyncVar] private GameObject objIdentity;
void Update () {
CheckIfPainting();
}
void CheckIfPainting(){
if(Input.GetMouseButtonDown(0)) {
if (Physics.Raycast (camTransform.TransformPoint (0, 0, 0.5f), camTransform.forward, out hit, range)) {
string objName = hit.transform.name;
CmdPaint(objName);
}
}
}
[ClientRpc]
void RpcPaint(){
objIdentity.GetComponent<Renderer>().material.color = objectColor;
}
[Command]
void CmdPaint(string name) {
objIdentity = GameObject.Find (name); //tell us what was hit
objectColor = new Color(Random.value, Random.value, Random.value, Random.value);
RpcPaint ();
}
}
я попробовал еще кучу решений, включая написание отдельного скрипта на объектах, цвет которых я хочу изменить, и включая функции [SyncVar] и hook. Я также пробовал отлаживать.Войти в систему каждая из функций, которые я ожидаю обновить объекты на клиентах, и они выполняются с ожидаемыми данными.
Я действительно не знаю, что еще делать. Я чувствую, что это очень простая вещь, которую я хочу сделать, но я не сталкивался с синхронизацией неигровых GameObject в любых вопросах, учебниках или других ресурсах. Любые идеи были бы полезны, спасибо.
4 ответов
Я нашел ответ. И это было очень трудно, так как почти каждый вопрос, пост, пример и т. д... Я мог найти об объектах игрока, а не об объектах не-игрока.
Итак, мне нужно использовать
Unity 5.3.2p3 назначьте полномочия клиента объектам, не являющимся игроками
для всех, кто заинтересован в настройке этого, это мой подход
Клиентской Стороне Компонент OnLocalPlayer - > команды вызова для назначения и удаления полномочий объекта путем передачи через объекты NetworkInstanceId. Вы можете добавить любой пользовательский интерфейс для вызова этих методов в этом компоненте
Сервер
[Command]
void CmdAssignObjectAuthority(NetworkInstanceId netInstanceId)
{
// Assign authority of this objects network instance id to the client
NetworkServer.objects[netInstanceId].AssignClientAuthority(connectionToClient);
}
[Command]
void CmdRemoveObjectAuthority(NetworkInstanceId netInstanceId)
{
// Removes the authority of this object network instance id to the client
NetworkServer.objects[netInstanceId].RemoveClientAuthority(connectionToClient);
}
Клиентской Стороне
3. Компонент объекта ->
OnStartAuthority() - разрешено отправлять команды на сервер
OnStopAuthority () - не разрешено отправлять команды на сервер
вот и все!
на 2018 год:
вместо использования "назначить полномочия объекта",
Я действительно рекомендую просто использовать
.SpawnWithClientAuthority
Это действительно очень легко.
на самом деле это просто!
[Command]
void CmdPleaseSpawnSomething() {
GameObject p = Instantiate(some_Prefab);
NetworkServer.SpawnWithClientAuthority(p, connectionToClient);
}
{в этом коде обратите внимание, что" connectionToClient " магически доступен без усилий-это означает "клиент", который вызвал эту команду.}
на клиенте (тот, который вы хотите "свое" дело), просто звоните CmdPleaseSpawnSomething()
.
Я имею в виду - вот и все, слава богу.
здесь есть длинное четкое объяснение:
https://forum.unity.com/threads/assign-authority-to-local-client-gameobject.371113/#post-3592541
Я делаю небольшую модификацию этого кода и добавляю возможность скрипта, если мы разместим игрока, он может внести изменения через raycasting.
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class Raycasting_Object : NetworkBehaviour {
private int range = 200;
// [SerializeField] private Transform camTransform;
private RaycastHit hit;
[SyncVar] private Color objectColor;
[SyncVar] private GameObject objectID;
private NetworkIdentity objNetId;
void Update () {
if (isLocalPlayer) {
CheckIfPainting ();
}
}
void CheckIfPainting(){
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay (ray.origin, ray.direction * 100, Color.cyan);
if(isLocalPlayer && Input.GetMouseButtonDown(0)) {
if (Physics.Raycast (ray.origin, ray.direction, out hit, range)) {
objectID = GameObject.Find (hit.transform.name); // this gets the object that is hit
Debug.Log(hit.transform.name);
objectColor = new Color(Random.value, Random.value, Random.value, Random.value); // I select the color here before doing anything else
CmdPaint(objectID, objectColor);
}
}
}
[ClientRpc]
void RpcPaint(GameObject obj, Color col){
obj.GetComponent<Renderer>().material.color = col; // this is the line that actually makes the change in color happen
}
[Command]
void CmdPaint(GameObject obj, Color col) {
objNetId = obj.GetComponent<NetworkIdentity> (); // get the object's network ID
objNetId.AssignClientAuthority (connectionToClient); // assign authority to the player who is changing the color
RpcPaint (obj, col); // usse a Client RPC function to "paint" the object on all clients
objNetId.RemoveClientAuthority (connectionToClient); // remove the authority from the player who changed the color
}
}