Spawning and Respawning

Checked with version: 5.3

-

Difficulty: Intermediate

Set Initial Spawn Positions for the Players

Currently the players are created and respawned at the origin point, or Vector3.zero. At the start of each game, unless we move one of the players before another joins, they will co-exist at the same point. In an ideal situation, players should spawn at different locations. The NetworkStartPosition component can be used to do this, as it has a built-in feature for handling spawn positions.

To create two unique spawn positions we will need to create two new GameObjects, each with a NetworkStartPosition component attached.

  • Create a new empty GameObject.
  • Rename the new GameObject “Spawn Position 1”.
  • With the Spawn Position 1 GameObject selected,
  • ... find and add the component Network > NetworkStartPosition.
  • ... set the Transform Position to (3, 0, 0).
  • Duplicate the Spawn Position 1 GameObject.
  • Rename this duplicated GameObject “Spawn Position 2”.
  • With the Spawn Position 2 GameObject selected,
  • ... set the Transform Position to (-3, 0, 0).
  • Select the Network Manager GameObject in the Hierarchy Window.
  • With the Network Manager GameObject selected,
  • ... open the Spawn Info foldout.
  • ... change the Player Spawn Method to Round Robin.

Because the Spawn Position GameObjects have the NetworkStartPosition component on them, they will be found automatically by the NetworkManager.

The NetworkManager will then use the Transform Position of these GameObjects with NetworkStartPositions attached as locations for spawning the new player GameObjects when their Clients connect to the Server.

There are two Player Spawn Methods: Random and Round Robin.

As their name suggests, Random will use a random spawn point from the available NetworkSpawnPositions, and Round Robin will cycle through all of the available spawn positions before reusing them.

With Random it is entirely possible that the same spawn position will be used by two or more player GameObjects, depending upon how many clients are connected. With Round Robin, the spawn points will only be reused if there are more Clients than spawn points.

Test these changes:

  • Build and Run this scene as a standalone application.
  • Click the Host button from the in-game UI to start this game as a Host.
  • Return to Unity.
  • Enter Play Mode.
  • Click the LAN Client button from the in-game UI to connect to the Host as a Client.

Now, when the game starts, the players are created at different positions in the scene.

  • Close the standalone player.
  • Return to Unity.
  • Exit Play Mode.

Set Respawn points

The last and final step to this basic example is to create a simple system that uses the NetworkStartPosition component on the Spawn Position GameObjects to build an array of spawn points to choose from when the player is respawned. This step is not strictly necessary for this Multiplayer Networking example, but makes the example feel a little more complete.

It is worth noting that an even simpler way of saving the respawn location would be to save the local player’s position in the Start function as the respawn point. This way the start position chosen by the Round Robin Player Spawn Method on the Network Manager would be “owned” by the player.

To create a respawning system we will need to create an array, find all of the GameObjects with a NetworkStartPosition attached, add them to the array and use their Transform Position as a respawn point. This is very similar to what is being done automatically by the Network Manager for the start point, but in this simple case, we won't have a Round Robin solution, just the Random one.

  • Open the Health script for editing.
  • Add a new array of the type NetworkStartPosition to hold the spawn points.
private NetworkStartPosition[] spawnPoints;

  • Add a Start function.
void Start ()
{

}

  • In the Start function, add a check to test if this GameObject is associated with the Local Player.
if (isLocalPlayer)
{
            
}

  • Add logic to find all instances of the NetworkStartPosition component and save them to the Spawn Points array.
spawnPoints = FindObjectsOfType<NetworkStartPosition>();

Note that this is the plural version: FindObjectsOfType.

  • In the RpcRespawn function, inside the isLocalPlayer check, remove the existing code:
// Set the player’s position to origin
transform.position = Vector3.zero;

  • In the RpcRespawn function, inside the isLocalPlayer check, update the code to use a random position from the array of spawn points.
// Set the spawn point to origin as a default value
Vector3 spawnPoint = Vector3.zero;

// If there is a spawn point array and the array is not empty, pick a spawn point at random
if (spawnPoints != null && spawnPoints.Length > 0)
{
    spawnPoint = spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position;
}

// Set the player’s position to the chosen spawn point
transform.position = spawnPoint;

The final script should look like this:

Health

Code snippet

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

public class Health : NetworkBehaviour {

    public const int maxHealth = 100;
    public bool destroyOnDeath;

    [SyncVar(hook = "OnChangeHealth")]
    public int currentHealth = maxHealth;

    public RectTransform healthBar;

    private NetworkStartPosition[] spawnPoints;

    void Start ()
    {
        if (isLocalPlayer)
        {
            spawnPoints = FindObjectsOfType();
        }
    }

    public void TakeDamage(int amount)
    {
        if (!isServer)
            return;
        
        currentHealth -= amount;
        if (currentHealth &lt;= 0)
        {
            if (destroyOnDeath)
            {
                Destroy(gameObject);
            } 
            else
            {
                currentHealth = maxHealth;

                // called on the Server, invoked on the Clients
                RpcRespawn();
            }
        }
    }

    void OnChangeHealth (int currentHealth )
    {
        healthBar.sizeDelta = new Vector2(currentHealth , healthBar.sizeDelta.y);
    }

    [ClientRpc]
    void RpcRespawn()
    {
        if (isLocalPlayer)
        {
            // Set the spawn point to origin as a default value
            Vector3 spawnPoint = Vector3.zero;

            // If there is a spawn point array and the array is not empty, pick one at random
            if (spawnPoints != null &amp;&amp; spawnPoints.Length &gt; 0)
            {
                spawnPoint = spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position;
            }

            // Set the player’s position to the chosen spawn point
            transform.position = spawnPoint;
        }
    }
}
  • Save the script.
  • Return to Unity.

Test these changes:

  • Build and Run this scene as a standalone application.
  • Click the Host button from the in-game UI to start this game as a Host.
  • Return to Unity.
  • Enter Play Mode.
  • Click the LAN Client button from the in-game UI to connect to the Host as a Client.

Now, when the game starts, the players are created at different positions in the scene. When a player’s current health drops to zero, the Player should respawn randomly at one of the existing spawn positions.

  • Close the standalone player.
  • Return to Unity.
  • Exit Play Mode.