Handling Non-Player objects

Checked with version: 5.3

-

Difficulty: Intermediate

Our current example has been focused primarily on the player GameObjects. Most games, however, have many non-player GameObjects that exist in the game world. For this example we will ignore environmental GameObjects but concentrate on non-player GameObjects such as enemies

While player GameObjects are spawned when a Client connects to the Host, enemy GameObjects need to be controlled by the Server.

In this section we will add an Enemy Spawner that creates non-player, enemy GameObjects that can be shot and killed by any of the players.

  • Create a new empty GameObject.
  • Rename the new GameObject “Enemy Spawner”
  • With the Enemy Spawner GameObject selected,
  • ... find and add the component: Network > NetworkIdentity
  • ... on the NetworkIdentity component, set the Server Only checkbox to true.

By setting Server Only to true, this prevents the Enemy Spawner from being sent to the Clients.

  • With the Enemy Spawner GameObject selected
  • ... create and add a new script called “EnemySpawner”
  • Open the script EnemySpawner for editing.
  • Replace all of the code in the script with the following simple EnemySpawner class:

EnemySpawner

Code snippet

using UnityEngine;
using UnityEngine.Networking;

public class EnemySpawner : NetworkBehaviour {

    public GameObject enemyPrefab;
    public int numberOfEnemies;

    public override void OnStartServer()
    {
        for (int i=0; i < numberOfEnemies; i++)
        {
            var spawnPosition = new Vector3(
                Random.Range(-8.0f, 8.0f),
                0.0f,
                Random.Range(-8.0f, 8.0f));

            var spawnRotation = Quaternion.Euler( 
                0.0f, 
                Random.Range(0,180), 
                0.0f);

            var enemy = (GameObject)Instantiate(enemyPrefab, spawnPosition, spawnRotation);
            NetworkServer.Spawn(enemy);
        }
    }
}

It is worth noting a few key elements in this script.

  1. The namespace UnityEngine.Networking is required.
  2. The class needs to derive from NetworkBehaviour.
  3. The class uses an implementation of the virtual function OnStartServer.
  4. When the server starts, a number of enemies are generated at a random position and rotation and then these are spawned using NetworkServer.Spawn(enemy).

OnStartServer is very similar to OnStartLocalPlayer, used earlier in this lesson to change the player GameObject’s color. In this case, OnStartServer is called on the Server when the Server starts listening to the Network. For more information on the virtual functions available from the NetworkBehaviour base class, please see the manual pages on NetworkBehaviour and Spawning or the Scripting Reference page on NetworkBehaviour.

  • Save the script.
  • Return to Unity.

Now that the Enemy Spawner has been created, we need enemy GameObjects to spawn.

For ease, we will use the player prefab as a base for the enemy. The enemy will need the NetworkIdentity and NetworkTransform components already attached to the Player prefab, as well the Health script and the Healthbar setup.

We will customize the enemy GameObject a little to identify the enemy as different from the player prefab.

  • Drag the Player prefab into the Hierarchy to create an instance of the Player GameObject in the scene.
  • Change the name of the Player GameObject to “Enemy”.
  • Drag this Enemy GameObject back into the Project Window to create a new Enemy prefab.

We create the new Enemy prefab at this point in the process to prevent any chance of saving our changes to the linked Player prefab. By creating a new prefab from the instance of the Player prefab in the scene, we link the prefab instance in the scene to the new prefab asset in the Project Window.

  • With the Enemy GameObject selected in the Hierarchy Window,
  • ... delete the child GameObject called Gun.

Unity will warn us that we will break the Prefab instance.

  • Click Continue.
  • With the Enemy GameObject selected,
  • ... delete the child GameObject called Bullet Spawn.
  • ... remove the PlayerController script from the root GameObject.

At this point, the enemy it technically ready to go, but it will look identical to the player GameObjects. Let’s add a few details to make the enemies different from the players.

First, we will simply reverse the color scheme.

  • Apply the Black Material to the Enemy GameObject.
  • Set the Material on the Visor GameObject to Default-Material.

Next, optionally, you can create a headpiece.

  • With the Enemy GameObject selected,
  • ... create a new Cube as a child GameObject.
  • Rename this new child GameObject "Mohawk”.
  • Set the Mohawk’s Transform Position to (0.0. 0.55, -0.15).
  • Set the Mohawk’s Transform Scale to (0.2, 1.0, 1.0).
  • Remove the Mohawk’s BoxCollider component.

The Enemy should look something like this:

description

  • Apply changes to the Enemy Prefab.
  • Delete the Enemy GameObject from the scene.
  • Save the scene.

Now that the Enemy prefab set up we need to finish this section by registering the Enemy prefab and adding the Enemyprefab to the Enemy Spawner.

  • Select the NetworkManager in the Hierarchy Window.
  • With the NetworkManager selected,
  • ... open the Spawn Info foldout.
  • ... in the list Registered Spawnable Prefabs, add a new row with the + button.
  • ... add the Enemy prefab to the new row in the Registered Spawnable Prefabs list.
  • Select the Enemy Spawner in the Hierarchy Window.
  • With the Enemy Spawner selected,
  • ... set the Enemy Prefab field to the Enemy prefab asset from the Project Window.
  • ... set the Number Of Enemies to a value of 4.

description

  • Save the Project.

Because the Enemy prefab has a Health script, just like the Player, the Bullet script should detect the enemy’s Health script in the same way it does on the Player, so no changes are needed here.

  • 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.

At this point, the first player and the four enemies should be created.

  • Move the Player GameObject.
  • Return to Unity.
  • Enter Play Mode.
  • Click the LAN Client button from the in-game UI to connect to the Host as a Client.

The second player should now be created, and the first player and all of the enemies should have been added to this instance of the game.

Shooting the enemies will cause them to lose health, but when their health reaches zero they are not respawned as none of the enemies will meet the isLocalPlayer check in RpcRespawn. Their current health will, however, be set back to maximum, as that is controlled by the Server.

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

Related documentation