Unity 5.1网络 - 为主机和所有客户端生成一个对象作为子对象

Jam*_*mes 5 network-programming multiplayer unity-game-engine unity-networking

我有一个可以装备多种武器的玩家对象.配备武器时,其变换的父级设置为其手.我已经搞砸了一段时间,并且不能让它对主机和客户端起作用.现在我正在尝试在服务器上装备武器,并告诉所有客户设置他们的父母变换.

public NetworkInstanceId weaponNetId; 

   [Command]
    void Cmd_EquipWeapon()
    {
        var weaponObject = Instantiate (Resources.Load ("Gun"),
                                        hand.position,
                                        Quaternion.Euler (0f, 0f, 0f)) as GameObject;

        weaponObject.transform.parent = hand;

        NetworkServer.Spawn (weaponObject);

        //set equipped weapon
        var weapon = weaponObject.GetComponent<Weapon> () as Weapon;

        weaponNetId = weaponObject.GetComponent<NetworkIdentity> ().netId;
        Rpc_SetParentGameobject (weaponNetId);
    }

    [ClientRpc]
    public void Rpc_SetParentGameobject(NetworkInstanceId netID)
    {   
        weaponNetId = netId;
    }
Run Code Online (Sandbox Code Playgroud)

在更新中,我正在更新武器转换

    void Update () {

    // set child weapon tranform on clients
    if (!isServer) {
        if (weaponNetId.Value != 0 && !armed) {
            GameObject child = NetworkServer.FindLocalObject (weaponNetId);


            if (child != null) {
                child.transform.parent = hand;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我知道这不是最优化的方法.但是现在我只是想让它以任何可能的方式工作,然后继续调整它.看起来它应该是一个简单的任务.

And*_*ard 10

我们在多人游戏中做了类似的事情.要使这项工作,您需要做一些事情.首先,概念:

正如您所发现的那样,在服务器上设置武器的父级是微不足道的.只需像在Unity中一样设置变换的父级.但是,在服务器上生成此对象后NetworkServer.Spawn,它将在场景根目录中的客户端上生成(生成的预制件之外的层次结构未同步).

所以为了调整客户端的层次结构,我建议你:

  • 使用SyncVar同步服务器和客户端之间父对象的netID.
  • 在客户端上生成对象时,使用synchronized netID查找父对象并将其设置为转换的父对象.

因此,我会调整你的代码看起来像这样.首先,在产生武器之前设置武器的父netId.这将确保在客户端上生成时,将设置netId.

[Command]
void Cmd_EquipWeapon()
{
    var weaponObject = Instantiate (Resources.Load ("Gun"),
                                    hand.position,
                                    Quaternion.Euler (0f, 0f, 0f)) as GameObject;
    weaponObject.parentNetId = hand.netId; // Set the parent network ID
    weaponObject.transform.parent = hand; // Set the parent transform on the server

    NetworkServer.Spawn (weaponObject); // Spawn the object
}
Run Code Online (Sandbox Code Playgroud)

然后在你的武器类中:

  • 添加parentNetId属性.
  • 将其标记为[SyncVar]在服务器和客户端副本之间进行同步.
  • 在客户端上生成时,使用netId查找父对象并将其设置为transform的父对象.

也许是这样的:

[SyncVar]
public NetworkInstanceId parentNetId;

public override void OnStartClient()
{
    // When we are spawned on the client,
    // find the parent object using its ID,
    // and set it to be our transform's parent.
    GameObject parentObject = ClientScene.FindLocalObject(parentNetId);
    transform.SetParent(parentObject.transform);
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我发现这篇文章非常有用,但我有一个小附录。

netId 将位于层次结构的根上,因此了解您可以使用 transform.Find 向下遍历层次结构很有用。

像这样的东西..

GameObject parentObject = ClientScene.FindLocalObject(parentNetId);
    string pathToWeaponHolder = "Obj/targetObj";

    transform.SetParent(parentObject.transform.Find(pathToWeaponHolder));
Run Code Online (Sandbox Code Playgroud)