Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How to respawn a player prefab?

Discussion in 'Multiplayer' started by Candytree, Jun 19, 2015.

  1. Candytree

    Candytree

    Joined:
    Jun 19, 2015
    Posts:
    3
    Hello everyone,

    we are currently using the networkLobbyManager to initiate a playerPrefAb and it's position based on the joined players. We want to have a round based game, so that after the round is finished, we can put every player back to the origin position and start another round. I haven't found anything similar in the documentation how to do this. All of it refers to connecting to the mainScene for once.
    Code (CSharp):
    1. ublic override GameObject OnLobbyServerCreateGamePlayer(NetworkConnection conn, short playerControllerId)
    2.     {
    3.         int n = conn.connectionId;
    4.         Debug.Log (n + "controller id");
    5.         Debug.Log (conn.ToString()+ "conn");
    6.         GameObject pref = player1;
    7.         Vector3 position= bottomLeft;
    8.         if (n == 1)
    9.         {
    10.             pref = player2;
    11.             position = topLeft;
    12.         }
    13.         else if (n == 2)
    14.         {
    15.             pref = player3;
    16.             position = topRight;
    17.         }
    18.         else if (n == 3)
    19.         {
    20.             pref = player4;
    21.             position = bottomRight;
    22.         }
    23.         return (GameObject) Instantiate(pref,position,Quaternion.identity);
    24.     }
    That is how we spawn a player right now. After it get's hit by an object in the game, it will be destroyed. Now after a round we want to recreate the playerPrefab , with the same connection ID on a specific position. How can we do that ?
     
  2. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    Switching Players
    The player object for a connection can be replaced with NetworkServer.ReplacePlayerForConnection . This takes the same arguments as AddPlayerForConnection, but allows there to already be a player for that connection. The old player object does not have to be destroyed. The NetworkLobbyManager uses this technique to switch from the LobbyPlayer to a game-play player when all the players in the lobby are ready.

    This can also be used to respawn a player after their object is destroyed. In some cases it is better to just disable an object and reset its game attributes on respawn, but to actually replace it with a new object you could use code like:

    Code (CSharp):
    1. class GameManager
    2. {
    3.     // call on server
    4.     public void PlayerWasKilled(Player oldPlayer)
    5.     {
    6.         var conn = oldPlayer.connectionToClient;
    7.         var newPlayer = Instantiate<GameObject>(playerPrefab);
    8.         Destroy(oldPlayer.gameObject);
    9.    
    10.         NetworkServer.ReplacePlayerForConnection(conn, newPlayer, 0);
    11.     }
    12. }
    13.  
    If the player object for a connection is destroyed, then that client will be unable to execute Commands. They can however still send network messages.

    To use ReplacePlayerForConnection you must have the NetworkConnection object for the player’s client to establish the relationship between the object and the client. This is usually the property connectionToClient on the NetworkBehaviour class, but if the old player has already been destroyed, then that may not be readily available.

    To find the connection, there are some lists available. If using the NetworkLobbyManager, then the lobby players are available in lobbySlots. Also, the NetworkServer has lists of connections and localConnections.
     
  3. Candytree

    Candytree

    Joined:
    Jun 19, 2015
    Posts:
    3
    Hi, thank you for your answer, but I am not quite sure how to get the connectionToClient outside of the LobbyNetworkManager script. PlayerLobby.slot doesn't give me a client object , and I don't know in what context to use connectionToClient. Could you specifiy what exactly do you mean with "some lists" ? I don't know yet how to find the connection without the LobbyNetworkManager.
    Also there are few things which came to my mind. Could I for example use on a collision the connection information pass that to the PlayerWasKilled and then replace it ? If I knew how to get the player connection outside of it, I guess then this would work .


    Thanks
     
    Last edited: Jun 19, 2015
  4. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    what do you mean "PlayerLobby.slot doesn't give me a client object"? It is a list of NetworkLobbyPlayer objects. Those are NetworkBehaviours, so they have a connectionToClient property.

    In any NetworkBehaviour script you can use "base.connectionToClient" to find the connection. If that object is not a player, then it will be null.
     
  5. Candytree

    Candytree

    Joined:
    Jun 19, 2015
    Posts:
    3
    Never mind got it, with lobby.lobbySlots[0].gameObject.SetActive(true);

    Also I will just use disable and enable the gameObject and always set them back to the origin position. That will probably be better in my case
     
  6. VenUk

    VenUk

    Joined:
    Jan 30, 2014
    Posts:
    10
    I've been working on this issue myself and came across this post which has helped me with re-spawning my player. Many thanks to "seanr" for the script above. However I found it re-spawned the player at the very centre of the map Vector(0,0,0); I've poked about a bit and modified the function so that it uses the other network components to spawn the player according to the spawn method chosen. Hopefully this will help other people out.

    To be completely clear I've used the 'Network Lobby' asset from the asset store and in the provided 'LobbyManager.cs' script I've added the modified method.

    public void PlayerWasKilled(Player oldPlayer)
    {
    TransformspawnTrans = GetStartPosition();

    var conn = oldPlayer.connectionToClient;
    var newPlayer = Instantiate(playerPrefab, spawnTrans.position, spawnTrans.rotation) as GameObject;
    Destroy(oldPlayer.gameObject);

    NetworkServer.ReplacePlayerForConnection(conn, newPlayer, oldPlayer.playerControllerId);
    }

    The difference is the GetStartPosition() method which gets the spawn point from the list of available spawn points. Then using that to instantiate the player at the random or round robin position from the LobbyManager game object.

    The player passed across is a class that inherits from the NetworkBehaviour

    public class Player : NetworkBehaviour

    In the awake function I get a reference to the LobbyManager

    public LobbyManager lobbyManager;

    lobbyManager = GameObject.FindGameObjectWithTag("LobbyManager").GetComponent<LobbyManager>();

    lobbyManager.PlayerWasKilled(player);