Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

Spawn objects from clients UNET

Discussion in 'Connected Games' started by hugettini, Jun 12, 2015.

  1. hugettini

    hugettini

    Joined:
    Apr 1, 2013
    Posts:
    19
    Hello, I'm testing the UNET system trying to switch my game from the old one to the new one, but I'm having some troubles.

    I already setup the server and the client with the network manager.

    I've spawned the player prefab (this object will control other players prefabs)
    There's a point which I need to spawn an object from the player prefab (this object has a NetworkIdentity and the player will control that object).

    If I spawn the object from the Client using

    Code (CSharp):
    1. GameObject go= (GameObject)Instantiate(prefab, transform.position, transform.rotation);
    2. NetworkServer.Spawn (go);
    The object is only spawned on the client.

    If I use a [Command] function to send it to the server, then it works ok and it's spawned everywhere.
    The problem is if the object is created on the server the client does not have the authority so I cannot call Command functions.
    Another problem is the instantiated gameobject is not destroyed when the player disconnects.

    What would be a good solution for that?

    Thank you!
     
    Last edited: Jun 12, 2015
    JoRouss, paluch.tiago and Miricks like this.
  2. Vapid-Linus

    Vapid-Linus

    Joined:
    Aug 6, 2013
    Posts:
    49
    Did you find an answer to this? I am in the same situation.
     
  3. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    only the server can spawn objects.
     
  4. hugettini

    hugettini

    Joined:
    Apr 1, 2013
    Posts:
    19
    As #searn says, only server can spawn objects.

    My work arround was to use the instantiated player prefab as a bridge to control the server instantiated gameObject.

    But now I'm facing a lag problem with that object, I didn't had time to solve that.

    I'll post if I can fix that secondary issue.
     
  5. Vapid-Linus

    Vapid-Linus

    Joined:
    Aug 6, 2013
    Posts:
    49
    So, there's no way to spawn another object that is controller by the player..?
     
  6. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,218
    Anyone got an answer to this? If a server spawns an object, how can the client call a function on one of its scripts?

    I have a building that is placed by CmdSpawnBuilding(). Any client/host can place a building that everyone sees, but they can't run any of its functions afterwards, even commands.

    Edit: You have to send the NetworkInstanceId of the object to the server. Get it from the object's NetworkIdentity component. Then the server can call whatever function you wanted on the gameobject.
     
    Last edited: Jul 27, 2015
    JoRouss likes this.
  7. EndUser

    EndUser

    Joined:
    Aug 12, 2013
    Posts:
    51
    Inaetaru likes this.
  8. EndUser

    EndUser

    Joined:
    Aug 12, 2013
    Posts:
    51
    It looks like you can choose from two routes:
    1) Your avatar sends message to his avatar (on your computer), and his avatar forwards message to server. Server's reaction is returned to his avatar on both of your computers.
    2) Your avatar sends message about his avatar to server, and server processes this message. The server returns new state of his avatar to both of your computers.
    Either way the authoritative server can verify messages from your computer.
    But I guess, the second way is more correct (although, first way is simpler). Yet, I have not reached this stage of my project yet.
     
  9. Inaetaru

    Inaetaru

    Joined:
    Aug 9, 2015
    Posts:
    16
    I'm having same problem, but after a few hours, I found the solution. It's not so easy.

    First, a few notes:
    • Networking uses something called "player controller id". It's a number (type: short) which is used to identify what you want to spawn. It's something like "spawned object type identificator". Value 0 (zero) is default, but all other values are free to use.
      • Note: it doesn't mean you can use only one prefab per single player controller id. You can select the prefab, send info about selected prefab to server through command (identify it with number, string or anything else which can be sent by command) and then use a player controller id (for example "1") to ask server to spawn the selected prefab.
    • In my system, I need to use something I call "default local player". It's instance of a prefab which was configured in NetworkManager class in field "Player Prefab" spawned by this very NetworkManager. From all players instances, the "local" one is the one representing (and controlled by) local player.
    My how-to:
    1. Define an ID for prefab type you want to spawn. This ID is player controller id I talked about above. In my example, I use number one.
    2. Derive a class from NetworkManager and override OnServerAddPlayer method. (Deriving from NetworkManager is purely because of the Add Player message - if you want to, you can use
      NetworkServer.RegisterHandler, but I found my way easier).
      Code (CSharp):
      1. public override void OnServerAddPlayer(NetworkConnection conn,
      2.     short playerControllerId)
      3. {
      4.     if(playerControllerId == 0)
      5.     {
      6.         // For default type use default implementation
      7.         // (spawnes prefab configured in inspector)
      8.         base.OnServerAddPlayer(conn, playerControllerId);
      9.     }
      10.     else if(playerControllerId == 1) // (Used 1 as id of my prefab type)
      11.     {
      12.         NetworkServer.AddPlayerForConnection(conn,
      13.             Instantiate(MyOtherPrefab), playerControllerId);
      14.     }
      15. }
      MyOtherPrefab is the prefab I want to spawn. This method spawnes the prefab on client request.
    3. Clients request spawning with ClientScene.AddPlayer() method. This method requires an instance of NetworkConnection. I'm really not sure where to take it "correctly", so I use default local player instance.
      Code (CSharp):
      1. ClientScene.AddPlayer(defaultLocalPlayer.connectionToClient, 1);
    4. However this won't work for client who is also a host. But for this special case, you can call NetworkServer.AddPlayerForConnection or NetworkManager.OnServerAddPlayer directly;
      Code (CSharp):
      1. if(defaultLocalPlayer.isServer)
      2. {
      3.     myNetworkManagerInstance.OnServerAddPlayer(
      4.        defaultLocalPlayer.connectionToClient, 1);
      5. }
      6. else
      7. {
      8.     ClientScene.AddPlayer(defaultLocalPlayer.connectionToClient, 1);
      9. }

    I hope my guide is helpful to someone...
     
  10. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    5.2 adds support for client authority of non-player objects:

    https://unity3d.com/unity/beta/unity5.2.0b1

    Networking: Added support for client-side authority for non-player objects.
    • The new function NetworkServer.SpawnWithClientAuthority(GameObject obj, NetworkConnection conn) allows authority to be assigned to a client by its connection when an object is created. This would typically be used in a command handler for a client asking to spawn an object, then the client's connection would be passed in. For example:
    Code (CSharp):
    1. [Command]
    2. void CmdSpawn()
    3. {
    4.     var go = (GameObject)Instantiate(otherPrefab, transform.position + new Vector3(0,1,0), Quaternion.identity);
    5.     NetworkServer.SpawnWithClientAuthority(go, base.connectionToClient);
    6. }
    • For setting the authority on objects after they are created, there are the new functions AssignClientAuthority(NetworkConnection conn) and RemoveClientAuthority(NetworkConnection conn) on the NetworkIdentity class. Note that only one client can be the authority for an object at a time. On the client that has authority, the function OnStartAuthority() is called, and the property hasAuthority will be true.

    • The set of objects that is owned by a client is available in the new property NetworkConnection.clientOwnedObjects which is a set of NetworkInstanceIds. This set can be used on the server when a message is received to ensure that the client that sent the message actually owns the object.
      When a client disconnects, the function DestroyPlayersForConnection now destroys all the objects owned by that connection, not just the player object. Objects which have their authority set to a client must have LocalPlayerAuthority set in their NetworkIdentity.
    • Networking: Added support for network [Command] calls from non-player objects with authority on a client. Since in 5.2 clients can have authority over non-player objects using NetworkServer.SpawnWithClientAuthority() or NetworkIdentity.AssignClientAuthority(), network Commands were extended from being allowed from just the player object to any object that is controlled by a client
     
  11. vanshika1012

    vanshika1012

    Joined:
    Sep 18, 2014
    Posts:
    34
    I just want my client to spawn a object but it is not spawning on Server. I have Unity pro and I am spawning it with NetworkServer.SpawnWithClientAuthority(), but no success. @seanr
     
  12. Morgenstern_1

    Morgenstern_1

    Joined:
    Jul 1, 2013
    Posts:
    34
    Clients cannot spawn objects, only the server can spawn networked objects.
     
  13. tiskolin

    tiskolin

    Joined:
    Sep 24, 2017
    Posts:
    241
    Then how would one spawn an object from a client trigger?
     
  14. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    963
    1. On the client, trigger an event.
    2. The event indicates the client must send a message with instructions to the server.
    3. Client sends the message to the server.
    4. Server receives the message.
    5. Server begins processing the message.
    6. Server sees that the message indicated the client wants a new object to be spawned.
    7. Server sends to the client, as well as all other clients that are listening to this message, a new message with new instructions.
    8. Each listening client receives the server's message.
    9. Each listening client processes the server's message.
    10. Each listening client sees the server wanted to spawn a new object for a particular client.
    11. Each listening client instantiates a new object.
    12. Each listening client assigns the ownership of the new instantiated object to that particular client.
    13. Each listening client now understands whom the new instantiated object belongs to.
    14. Each listening client handles the newly instantiated object accordingly.
    TLDR; Client A sends a message to Server, telling the Server to send back a message to all clients A through Z that a new object is about to spawn, and that object belongs to Client A.
     
  15. GibTreaty

    GibTreaty

    Joined:
    Aug 25, 2010
    Posts:
    789
    Only the server can assign authority so really, the client just needs to send a request to the server to spawn the thing. Then the server can spawn the thing in question and use that client's NetworkConnection as the one to assign authority to.
     
  16. Di_o

    Di_o

    Joined:
    May 10, 2016
    Posts:
    38

    PLEEEEASE GIVE US A CODE EXAMPLE
     
  17. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    5,236
    Unet was deprecated a year ago, you should really be moving on instead of churning up old threads about stuff that is removed from the current scripting reference. But since no one seems to listen, put the below on the Player GameObject.

    Code (csharp):
    1. public GameObject SomeNetworkObjectPrefab;
    2.  
    3. [Command]
    4. void CmdSpawnSomeNetworkObjectWithClientAuthority()
    5. {
    6.     GameObject someNetworkObject = Instantiate(SomeNetworkObjectPrefab);
    7.     NetworkServer.SpawnWithClientAuthority(someNetworkObject, connectionToClient);
    8. }
     
  18. Di_o

    Di_o

    Joined:
    May 10, 2016
    Posts:
    38
    I wish I could. I really do...

    The big problem is that there is nothing out there to safely implement all the other stuff, that I'm using in my project. I would like to just go on vacation until everything is finally ready to use. This is not gonna happen, though...
     
    Last edited: May 15, 2019
    tiskolin likes this.
  19. tiskolin

    tiskolin

    Joined:
    Sep 24, 2017
    Posts:
    241
    I feel the same way. I don't want to use UNET because of its deprecation, however, the new multiplayer system isn't ready yet. So I'm probably going to stick with singleplayer and local multiplayer games for now, at least until the new multiplayer system is ready.
     
    GibTreaty likes this.
  20. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    5,236
    Unity now is on their 3rd networking implementation. Both previous times they were released half baked with little follow up. Unity has said or done nothing to indicate that this round will be handled differently, and past behavior says you shouldn't be waiting breathlessly for what Unity releases for networking. Especially when networking isn't a feature that even needs an implementation from Unity directly.

    They've been working a year on a system which looks like something someone knowledgeable in writing networking code could have built in a few weeks. Most of the blog posts on the topic focus on their monetized server hosting rather than the networking API. The networking API appears to me to not be a priority at Unity or it would have been fully featured and released months ago. Just go with a solution not from Unity.
     
    Last edited: May 15, 2019
  21. Di_o

    Di_o

    Joined:
    May 10, 2016
    Posts:
    38

    You should talk to my boss ;)