Unet NetworkServer.Spawn() not working

Hello, I’m try to spawn objects over the network and to make it simple I told it to spawn a cube. The cube has the two networking components Network Identity and Network Transform. I have this code to make the cube.

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class Network_BuilderGUI : NetworkBehaviour 
{
	public GameObject TestPart;
	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () 
	{
		if(Input.GetMouseButtonDown(0))
		{
			print ("Create");
			CreatePart();
		}
	}

	//[Command]
	void CreatePart()
	{
		GameObject Te = (GameObject)Instantiate(TestPart,transform.position,transform.rotation);
		NetworkServer.Spawn(TestPart);
	}
}

Now it seems to be that the cube gets created by the client that started it, but then I get error on the other clients “Failed to spawn server object” am I missing something because seems the manual states to do it this way?

Ok I found that you have to register a object for it to work. Is there a way though to create objects for everyone to see without the use of registering prefabs?

How did you register the prefab/object?

When your in NetworkManager component open up Spawn Info. Then there should be an area called Registered Spawnable Prefabs. Click the + icon and add it in then it should work. I've tried using the code version to add which is ClientScene.RegisteredPrefab() but doesn't seem to work.

Ah that makes sense. But now when i shoot on the client they don't appear on the server. But they do when i shoot on the server. Any idea why this is? Sorry btw for not answering your questions but asking questions instead :p

That's fine. I don't have any idea for the shooting. Sorry. Unet is brand new so I'm still learning it. Hopefully there is a way to create objects over the server like the old networking "Network.Instantiate" Because I have to many objects for registering.

5 Answers

5

@Guardian2300

A host is a special thing here. Mainly it’s a server but it’s a local client as well.

The registering is required for the clients to be able to find the spawnable prefabs.

I’m trying to provide you a simple “shooting” example, step by step

PART 1

  1. Create a new scene and save it

  2. Create a new game object, name it NetworkManager

  3. Add two components to it: NetworkManager and NetworkManagerHUD

  4. Create a new game object called Player. This will be our player to be spawned when connected to the server.

  5. Add a NetworkIdentity component to this object. Check “Local Player Authority”.

  6. Add a NetworkTransform component as well. This will handle the transform syncing automatically.

  7. Add a child cube or something to be able to see where the player is.

  8. Create a new (c#) script and call it Player as well. Here is the commented code:

    using UnityEngine;
    

    using UnityEngine.Networking;

    public class Player : NetworkBehaviour
    {
    public float _moveSpeed = 3.0f;

    private Vector3 _velocity;
    
    public override void OnStartLocalPlayer()
    {
        base.OnStartLocalPlayer();
    
        // you can use this function to do things like create camera, audio listeners, etc.
        // so things which has to be done only for our player
    }
    
    private void Update()
    {
        // isLocalPlayer is true for the client who "owns" the player object
        // we only want input handling for our player
        if (!base.isLocalPlayer)
            return;
    
        // handle input here...
    
        _velocity = Vector3.zero;
    
        if (Input.GetKey(KeyCode.W))
            ++_velocity.z;
        if (Input.GetKey(KeyCode.S))
            --_velocity.z;
        if (Input.GetKey(KeyCode.A))
            --_velocity.x;
        if (Input.GetKey(KeyCode.D))
            ++_velocity.x;
    
        _velocity.Normalize();
    }
    
    private void FixedUpdate()
    {
        // because Local Player Authority is true, the client has to move the player
        // only the resulting transform will be sent to the server and to the other clients
        if (!base.isLocalPlayer)
            return;
    
        // if that flag is not true, we should check that the code runs only on server
        // it could be done by checking base.isServer
    
        // transforming and other authoritive stuff here...
    
        transform.position += _velocity * Time.deltaTime * _moveSpeed;
    }
    

    }

  9. After adding the newly created Player component to the Player object, create a prefab from this object (drag & drop from the Hiearchy to the Assets tab)

  10. Select the NetworkManager, expand “Spawn Info” section, and assign the previously created prefab to the Player Prefab.

  11. If it was successful (no error messages, etc), delete the Player object from the scene.

  12. Now, if you build the game, and start the standalone, a basic movement is working. One of the game has to be the host, the other is a client (ofc, create the host first)

PART 2

  1. Create a new game object, call it Bullet

  2. Add a NetworkIdentity and a NetworkTransform components to it - note the Local Player Authority is not checked this time!

  3. Add a child sphere to be able to see the bullet

  4. Create a new (c#) script, call it Bullet. Here is the code:

     using UnityEngine;
    

    using UnityEngine.Networking;

    public class Bullet : NetworkBehaviour
    {
    public float moveSpeed = 10.0f;
    public Vector3 velocity;

     private void FixedUpdate()
     {
         // we want the bullet to be updated only on the server
         if (!base.isServer)
             return;
    
         // transform bullet on the server
         transform.position += velocity * Time.deltaTime * moveSpeed;
     }
    

    }

  5. Add the newly created Bullet script to the Bullet object.

  6. Create a prefab from this object

  7. Select the NetworkManager object and in the Spawn Info section under the Registered Spawnable Prefabs, press the + icon and assign the bullet prefab to the empty space. Now, you can remove the Bullet object from the scene

  8. This registering means that your clients will be able to spawn this object. This is a must-have step.

  9. The client cannot spawn networked object itself, it can just ask the server to spawn a new one. To have shooting, we have to modify our Player class

     // Command means when the client call this function, it's "forwarded" to the server
    

    // and the code will actually run on server side
    // NOTE: the function name has to start with “Cmd”
    [Command]
    public void Cmd_Shoot()
    {
    // create server-side instance
    GameObject obj = (GameObject)Instantiate(bulletPrefab, transform.position, Quaternion.identity);
    // setup bullet component
    Bullet bullet = obj.GetComponent();
    bullet.velocity = transform.forward;
    // destroy after 2 secs
    Destroy(obj, 2.0f);
    // spawn on the clients
    NetworkServer.Spawn(obj);
    }

    private void Update()
    {
    // … same as before

     // when pressing the space button, ask the server to spawn a bullet
     if (Input.GetKeyDown(KeyCode.Space))
         Cmd_Shoot();
    

    }

  10. Select the Player prefab, and assign the Bullet prefab to the corresponding place.

  11. Build and test it. You can now move and shoot bullets. :slight_smile:

Here is the completed project. The source code looks better than here. :slight_smile:
And Here is a “tutorial” from the Unite 2014.

Awesome, Thank you very much for helping me with this.

So far I got it to create a cube on the clients and host at the position of the players. The only problem I'm running into is that when you join the match the objects don't get created for the new clients. The tutorial video I believe stated that the objects should automatically get created and updated with new clients. But I get errors saying that it won't spawn the object. How would I go at controlling this?

Does the object have NetworkIdentity component? Have you added the NetworkTransform component to it? Anyway, have you tried the attached sample project? Edit: Oh, and you can try to build the standalone, run the server/host on it, but the client in the editor. In this case, you can see client-side error messages appear on the console and the hiearchy (the spawned objects) as well.

Yes, Yes, I just tried your program and if there are bullets still current in scene when client joins the client gets the error Failed to spawn server object, UnityEngine.Networking.NetworkIdentity

Sorry, my bad... It seems like I forgot to attach the meta files. :) Now I tried to create a new project, extract the assets, build, and run it twice, and it works for me. I created a host, then in the other window, I join as a client. [Here][1] is the fixed version of the completed project. :) NOTE: the metafiles are hidden files, take care! If it's not working then... I don't know. Which version of Unity are you using? [1]: https://www.dropbox.com/s/6hjlofla68k2080/NetworkSpawningFixed.zip?dl=0

//[Command]
void CreatePart()
{
GameObject Te = (GameObject)Instantiate(TestPart,transform.position,transform.rotation);
// You had “TestPart” here. You need to put “Te” because its actualy the object you are instantiating
NetworkServer.Spawn(Te);
}

Woops I believe I was trying multiple different lines of code. Will I still have to register the game object to get it to create over server. I have too many prefabs to register them all.

I can’t comment anymore so I have to make a new answer. I try doing the unet tutorials on youtube and doesn’t want to create the object of the client the same way I am having issues with the current NetworkServer.Spawn(). This only works on the host but even then I can’t tell the clients to tell server to create Object.

I’ve tried using OnStartServer() where the function CreatePart() is supposed to create the object for the server.

void CreatePart()
{
		GameObject Te =  (GameObject)Instantiate(TestPart,transform.position,transform.rotation);
		ClientScene.RegisterPrefab(Te);
		NetworkServer.Spawn(Te);
}

Gives me an error saying on the client side can’t spawn object.
I’ve tried [Server] and [Command] Attributes but doesn’t work either. I don’t understand what I’m missing because either I get errors or the object doesn’t get spawned.

Is this not a simple “you haven’t added the prefab to the spawnable objects list in Network Manager” error?

Its a different case to where I have too many prefabs to add them in the network manager. I have to do it through code.

@Gaurdian @Ibzy Is there any simplier way just to spawn object from client to all other clients + host.

//[Command]
void CreatePart()
{
GameObject Te = (GameObject)Instantiate(TestPart,transform.position,transform.rotation);
// You had “TestPart” here. You need to put “Te” because its actualy the object you are instantiating
NetworkServer.Spawn(Te);
}