UNET Spawn object as a child object.

Hi,

I’m testing the new Unity Networking system. I’m wondering how can I spawn a networked object as a child object?

So I have a player object which is spawned by calling NetworkServer.AddPlayerForConnection. This object does not have any model, just an empty GameObject with a script attached to it.

After this step, I would like to spawn a child object which would be the real model with animations and other components. This would be useful for other things like weapon in the hand and so on…

Any ideas? Thanks!

It took a while for me to fugure this out, but it seems i found a very simple solution to tell the server where to spawn an object and get it synced on all clients. It doesn’t require NetworkTransform component on the spawned object or custom script attached to the spawned block. And it seems i can use gameObject as command or RPC parameter directly with UNET.

	[Client]
	void CreateBlock()//
	{
		if (!isLocalPlayer){return;}
		if (Input.GetKey (KeyCode.U))
		{
			//if(allowCreation)
			{
				CmdCreateBlock(preCreationPosition,preCreationRotation, preCreationParentAccordingToType.gameObject);
				
			}
		}
	}

	[Command]
	public void CmdCreateBlock(Vector3 p, Quaternion r, GameObject g)//since i want client to tell server object position i need these parameters
	{
		connBlockFromObject = (GameObject)GameObject.Instantiate (cube, p, r);
		connBlockFromObject.transform.parent = g.transform;
		NetworkServer.Spawn(connBlockFromObject);
		RpcSyncBlockOnce (connBlockFromObject.transform.localPosition, connBlockFromObject.transform.localRotation, connBlockFromObject, connBlockFromObject.transform.parent.gameObject);
	}

	[ClientRpc]
	public void RpcSyncBlockOnce(Vector3 localPos, Quaternion localRot, GameObject block, GameObject parent)
	{
		block.transform.parent = parent.transform;
		block.transform.localPosition = localPos;
		block.transform.localRotation = localRot;
	}

I’ve done a simple Message to link an object to another one.

public class Message
{
    // used for auto-increment
    private enum Type
    {
        SetParent = MsgType.Highest + 1
    }

    public const short SetParent = (short)Type.SetParent;
}

public class SetParentMessage : MessageBase
{
    public NetworkInstanceId netId;
    public NetworkInstanceId parentNetId;

    public SetParentMessage()
    {
    }
    public SetParentMessage(GameObject gameObject, GameObject parent)
    {
        netId = GetNetId(gameObject);
        parentNetId = GetNetId(parent);
    }

    private static NetworkInstanceId GetNetId(GameObject obj)
    {
        // NOTE: no error handling
        return obj.GetComponent<NetworkIdentity>().netId;
    }
}

This message can be used to link a networked object to another one. When the server spawns the objects, it can call the following function

private static void LinkToParent(GameObject child, GameObject parent)
{
    child.transform.parent = parent.transform;
    NetworkServer.SendToAll(Message.SetParent, new SetParentMessage(child, parent));
}

The message handler has to be registered in the client-side. This is done by calling

RegisterHandler(Message.SetParent, OnSetParent);

And finally, the OnSetParent function simply finds the local objects and link them.

private void OnSetParent(NetworkMessage netMsg)
{
    SetParentMessage msg = netMsg.ReadMessage<SetParentMessage>();
    ClientScene.objects[msg.netId].transform.parent = ClientScene.objects[msg.parentNetId].transform;
}

I’m preparing to work on syncing armor and weapons over the network and I had an idea that does not involve spawning over the network or adding network identity to every armor/weapon prefab.

I have not tried this yet so let me know if there’s a better way and why.

Basically, each character has a equipped inventory, this inventory is set up as SyncVars that update all clients when an inventory item is added, changed, or removed.

When a equipment slot value changes, a hook is caught on the client that reads the change and locally instantiates the item prefab associated with that item and sets it to the correct parent object. The hook and SyncVars are placed on a script that is a component of the root object so reference is easy.