Как синхронизировать свойства неигрового 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
    }
}