Conceptos del Sistema de Red
Utilizando el NetworkManager (Administrador de red)

Configurando un proyecto Multijugador desde el principio

Este documento describe los pasos para configurar un nuevo proyecto multijugador desde cero utilizando el nuevo sistema de networking (comunicación/redes). Este proceso paso-por-paso es genérico, pero puede ser personalizado para muchos tipos de juegos multijugador una vez haya empezado.

Para empezar, cree un nuevo proyecto de Unity vacío.

Configuración del NetworkManager

El primer paso es crear un objeto NetworkManager en el proyecto:

  • Agregue un nuevo game object vacío, del menú Game Object -> Create Empty.
  • Encuentre el nuevo objeto creado en la Vista de Jerarquía y seleccionelo
  • Re-nombre el objeto a “NetworkManager” desde el menú de contexto que surge al hacer click derecho o haciéndole click al nombre del objeto y escribiendo.
  • En la ventana del inspector del objeto, oprima el botón Add Component
  • Encuentre el componente Network -> NetworkManager y agreguelo al objeto. Este componente maneja el estado de network (red) del juego.
  • Encuentre el componente Network -> NetworkManagerHUD y agreguelo al objeto. Este componente proporciona una interfaz de usuario simple en su juego para controlar el estado del network (red).

Para más detalles, ver Utilizando el NetworkManager.

Configure el Player Prefab

El siguiente paso es configurar el Unity Prefab que representa el jugador en el juego. Por defecto, el NetworkManger instancia un objeto para cada jugador al clonar el player prefab. En este ejemplo, el objeto jugador será un simple cubo.

  • Cree un nuevo Cubo desde el menú Game Object -> 3D Object -> Cube
  • Encuentre el cubo en la vista de jerarquía y seleccionelo
  • Re-nombre el objeto a “PlayerCube”
  • En la ventana del inspector del objeto oprima el botón Add Component
  • Agregue el componente Network -> NetworkIdentity al objeto. Este componente se utiliza para identificar el objeto entre el servidor y los clientes.
  • Configure la casilla de verificación “Local Player Authority” en el NetworkIdentity a true. Esto le permitirá al cliente controlar el movimiento del objeto jugador.
  • Convierta a un prefab el objeto player cube al arrastrarlo a la ventana Assets. Esto va a crear un prefab llamado “PlayerCube”
  • Borre el objeto PlayerCube de la escena - no lo necesitamos ahora que tenemos un prefab

Ver Objetos Player (Jugador).

Registre el Player Prefab

Una vez el prefab del jugador es creado, esta debe ser registrado con el sistema del network (red).

  • Encuentre el objeto NetworkManager en la vista de jerarquía y seleccionelo
  • Abra la propiedad desplegable “Spawn Info” del inspector del NetworkManager
  • Encuentre la ranura/casilla “Player Prefab”
  • Arrastre el PlayerCube prefab a la ranura “Player Prefab”

Ahora es un buen momento para guardar el proyecto por primera vez. Del menú File -> Save Project, guarde el proyecto. Usted también debería guardar la escena. Llamemos esta escena la escena “offline”.

Movimiento del Jugador (Versión de un solo jugador)

Una de las funcionalidades principales del juego es mover el objeto jugador. Esto se hará primero sin el networking (red), por lo que solo funcionará en el modo de un solo jugador.

  • Encuentre el prefab PlayerCube en la vista de los Assets.
  • Oprima el botón Add Component y escoja “New Script”
  • Ingrese el nombre “PlayerMove” para el nuevo nombre del script. Luego un nuevo script será creado.
  • Abra este script en un editor (como lo es Visual Studio) al hacer doble click
  • Agregue este código de movimiento simple al script:
using UnityEngine;

public class PlayerMove : MonoBehaviour
{
    void Update()
    {
        var x = Input.GetAxis("Horizontal")*0.1f;
        var z = Input.GetAxis("Vertical")*0.1f;

        transform.Translate(x, 0, z);
    }
}

Esto hace que el cubo sea controlado por las teclas flechas o un controlador pad. El cubo solamente se mueve en el cliente ahorita - no está networked (en red).

Guarde el proyecto nuevamente.

Pruebe un Juego Alojado

Ingrese al modo de juego en el editor oprimiendo el botón de reproducción. Usted debe ver la interfaz de usuario por defecto del NetworkManagerHUD:

Presione “Host” para iniciar el juego como el host (anfitrión) del juego. Esto va a causar que un objeto jugador sea creado, y el HUD va a cambiar para mostrar que el servidor está activo. Este juego está corriendo como “host” (anfitrión) - el cual es un servidor y un cliente en el mismo proceso.

Ver Conceptos de Network (red).

Al oprimir las teclas de flecha el objeto player cube debe moverse.

Salga del modo de juego al oprimir el botón de stop en el editor.

Pruebe el Movimiento del Jugador para un Cliente

  • Utilice el menú File -> Build Settings para abrir el dialogo de los Build Settings
  • Agregue la escena actual de la construcción al oprimir el botón “Add Open Scenes”
  • Cree una construcción al oprimir el botón “Build and Run”. Esto pedirá un nombre para el ejecutable, ingrese un nombre como “networkTest”
  • Un reproductor stand-alone va a ejecutarse, y mostrará un dialogo para escoger la resolución.
  • Escoja la casilla de verificación “windowed” y una resolución menor que 640x480
  • El reproductor stand-alone va a iniciar y mostrará el NetworkManager HUD.
  • Escoja “Host” del menú para iniciar como un anfitrión. Un player cube debe ser creado
  • Presione las flechas de tecla para mover el cubo jugador alrededor un poco
  • Devuélvase al editor y cierre el dialogo de los Build Settings.
  • Ingrese al modo de juego con el botón de jugar
  • De la interfaz de usuario NetworkManagerHUD, escoja “LAN Client” para conectarse al anfitrión (host) como un cliente
  • Debería haber dos cubos, uno para el jugador local en el host (anfitrión) y uno para el jugador remoto de este cliente
  • Presione las teclas flechas para mover el cubo
  • Ambos cubos actualmente se mueven! Esto se debe a que el script no está atento al network (red).

Haga que el Movimiento del Jugador esté Networked (en red)

  • Cierre el reproductor stand-alone
  • Sálgase del modo de juego en el editor
  • Abra el script PlayerMove.
  • Actualice el script para mover solamente el jugador local
  • Agregue “using UnityEngine.Networking”
  • Cambie “MonoBehaviour” a “NetworkBehaviour”
  • Agregue una revisión para “isLocalPlayer” (esJugadorLocal) en la función Update, para que solamente el jugador local procese input
using UnityEngine;
using UnityEngine.Networking;

public class PlayerMove : NetworkBehaviour
{
    void Update()
    {
        if (!isLocalPlayer)
            return;

        var x = Input.GetAxis("Horizontal")*0.1f;
        var z = Input.GetAxis("Vertical")*0.1f;

        transform.Translate(x, 0, z);
    }
}
  • Encuentre el prefab PlayerCube en la vista de Assets y seleccionelo
  • Oprima el botón “Add Component” y agregue el componente Networking -> NetworkTransform. Este componente hace que el objeto sincronice su posición a través de la red.
  • Guarde nuevamente el proyecto

Pruebe el Movimiento Multijugador

  • Construya y corra el reproductor stand-alone nuevamente e inicie como host (anfitrión)
  • Ingrese al modo de juego en el editor y conéctese como un cliente
  • Los objetos jugadores deberían moverse independientemente del otro, y están controlados por el jugador local en sus clientes.

Identifique a su Jugador

Los cubos en el juego están actualmente todos en blanco, entonces el usuario no puede decir cuál es su cubo. Para identificar el jugador, haremos el cubo local el jugador rojo.

  • Abra el script PlayerMove
  • Agregue una implementación de la función OnStartLocalPlayer para cambiar el color del objeto jugador.
    public override void OnStartLocalPlayer()
        {
            GetComponent<MeshRenderer>().material.color = Color.red;
        }

Esta función solamente se llama en el jugador local en su cliente. Esto hará que el usuario vea su cubo como rojo. La función OnStartLocalPlayer es un buen lugar para dar una inicialización que es solamente para el jugador local, tal como configurar cámaras e input.

También hay otras funciones virtuales útiles en la clase base NetworkBehaviour. Ver Spawning.

  • Construya y ejecute el juego
  • El cubo controlado por el jugador local debería estar rojo, mientras los otros todavía están en blanco.

Disparándo balas (No Networked (sin red))

Una característica común en los juegos multijugador es hacer que los jugadores disparen balas. Esta sección agrega balas sin estar networked (en red) para mostrar el ejemplo. El networking para las balas se agrega en la siguiente sección.

  • Cree un game object sphere (esfera)
  • Re-nombre el objeto sphere (esfera) a “Bullet”
  • Cambie la escala de la bala de 1.0 a 0.2
  • Arrastre la bullet (bala) a la carpeta assets para convertirla en un prefab
  • Borre el objeto bullet de la escena
  • Agregue un componente Rigidbody a la bullet
  • Configure la casilla de verificación “Use Gravity” al rigidbody a false
  • Actualice el script PlayerMove para disparar balas:
  • Agregue una ranura pública al prefab de la bala
  • Agregue el manejo del input en la función Update()
  • Agregue una función para disparar una bullet (bala)
using UnityEngine;
using UnityEngine.Networking;

public class PlayerMove : NetworkBehaviour
{
    public GameObject bulletPrefab;

    public override void OnStartLocalPlayer()
    {
        GetComponent<MeshRenderer>().material.color = Color.red;
    }

    void Update()
    {
        if (!isLocalPlayer)
            return;

        var x = Input.GetAxis("Horizontal")*0.1f;
        var z = Input.GetAxis("Vertical")*0.1f;

        transform.Translate(x, 0, z);

        if (Input.GetKeyDown(KeyCode.Space))
        {
            Fire();
        }
    }

    void Fire()
    {
        // create the bullet object from the bullet prefab
        var bullet = (GameObject)Instantiate(
            bulletPrefab,
            transform.position - transform.forward,
            Quaternion.identity);

        // make the bullet move away in front of the player
        bullet.GetComponent<Rigidbody>().velocity = -transform.forward*4;
        
        // make bullet disappear after 2 seconds
        Destroy(bullet, 2.0f);        
    }
}
  • Guarde el script y devuelva al editor
  • Seleccione el prefab PlayerCube y encuentre el componente PlayerMove
  • Encuentre la ranura bulletPrefab en el componente
  • Arrastre el prefab bullet a la ranura bulletPrefab
  • Haga una construcción y empiece el reproductor stand-alone como anfitrión
  • Ingrese al modo de juego en el editor y conéctese como un cliente
  • Al presionar la barra de espacios se debe causar que una bala sea creada y disparada del objeto jugador
  • La bala no se dispara en otros clientes, solamente en aquellos donde la barra de espacio sea presionada.

Disparando Balas con Networking

Esta sección agrega el networking a las balas en el ejemplo.

  • Encuentre el prefab bullet (bala) y seleccionelo
  • Agregue NetworkIdentity al prefab de la bala
  • Agregue el componente NetworkTransform al prefab de la bala
  • Configure el send rate (tasa de envío) a cero en el componente NetworkTransform en el prefab de la bala. Esta bala no cambia dirección o velocidad después de que sea disparada, por lo que no tiene que enviar actualizaciones de movimiento.
  • Seleccione el NetworkManager y abra el desplegable del “Spawn Info”
  • Agregue un nuevo prefab de spawn (generación) con un botón (+)
  • Arrastre el prefab de la bala a una nueva ranura prefab de spawn (generación)
  • Abra el script PlayerMove
  • Actualice el script PlayerMove para poner la bala en network (red):
  • Cambie la función Fire (de disparo) a que sea un comando networked (en red), al agregar el atributo personalizado [Command] y el prefijo “Cmd”
  • Utilice Use Network.Spawn() en el objeto de la bala
using UnityEngine;
using UnityEngine.Networking;

public class PlayerMove : NetworkBehaviour
{
    public GameObject bulletPrefab;
    
    public override void OnStartLocalPlayer()
    {
        GetComponent<MeshRenderer>().material.color = Color.red;
    }

    [Command]
    void CmdFire()
    {
       // This [Command] code is run on the server!

       // create the bullet object locally
       var bullet = (GameObject)Instantiate(
            bulletPrefab,
            transform.position - transform.forward,
            Quaternion.identity);

       bullet.GetComponent<Rigidbody>().velocity = -transform.forward*4;
       
       // spawn the bullet on the clients
       NetworkServer.Spawn(bullet);
       
       // when the bullet is destroyed on the server it will automaticaly be destroyed on clients
       Destroy(bullet, 2.0f);
    }

    void Update()
    {
        if (!isLocalPlayer)
            return;

        var x = Input.GetAxis("Horizontal")*0.1f;
        var z = Input.GetAxis("Vertical")*0.1f;

        transform.Translate(x, 0, z);

        if (Input.GetKeyDown(KeyCode.Space))
        {
            // Command function is called from the client, but invoked on the server
            CmdFire();
        }
    }
}

Este código utiliza un Command para disparar la bullet (bala) en el servidor. Para más información ver Networked Actions.

  • Haga una construcción y empiece el reproductor stand-alone como anfitrión
  • Ingrese al modo de juego en el editor y conéctese como un cliente
  • Al oprimir la barra de espacios se debería disparar una bala del jugador correcto (solamente) en todos los clientes

Colisiones de la bullet (bala)

Esto agrega un manejador de colisiones para que las balas desaparezcan cuando golpeen el objeto player cube.

  • Encuentre el prefab bullet (bala) y seleccionelo
  • Escoja el botón Add Component y agregue un nuevo script
  • Llame el nuevo script “Bullet”
  • Abra el nuevo script y agregue el manejador de colisión que destruye la bala cuando golpee un objeto jugador
using UnityEngine;

public class Bullet : MonoBehaviour
{
    void OnCollisionEnter(Collision collision)
    {
        var hit = collision.gameObject;
        var hitPlayer = hit.GetComponent<PlayerMove>();
        if (hitPlayer != null)
        {
            Destroy(gameObject);
        }
    }
}

Ahora cuando una bala golpea un objeto jugador esta será destruida. Cuando la bala en el servidor sea destruida, este será destruido en los clientes también debido a que es un objeto generado y manejado por el network (red).

Estado del jugador (Health (salud) no networked (en red))

Una característica común de las balas es que el objeto jugador tiene una propiedad “health” (saludo) que inicia en un valor completo y luego es reducido cuando el jugador toma daños de una bala que lo está golpeando. Esta sección agrega salud no networked (en red) al objeto jugador.

  • Seleccione el prefab PlayerCube
  • Escoja el botón Add Component y agregue un nuevo script
  • Llame el script “Combat”
  • Abra el script Combat, agregue las variables de health y la función TakeDamage
using UnityEngine;

public class Combat : MonoBehaviour 
{
    public const int maxHealth = 100;
    public int health = maxHealth;

    public void TakeDamage(int amount)
    {
        health -= amount;
        if (health <= 0)
        {
            health = 0;
            Debug.Log("Dead!");
        }
    }
}

El script bullet necesita ser actualizado para llamar la función TakeDamage en un golpe. * Abra el script bullet * Agregue un llamado a TakeDamage() del script Combat en la función que maneja colisiones

using UnityEngine;

public class Bullet : MonoBehaviour
{
    void OnCollisionEnter(Collision collision)
    {
        var hit = collision.gameObject;
        var hitPlayer = hit.GetComponent<PlayerMove>();
        if (hitPlayer != null)
        {
            var combat = hit.GetComponent<Combat>();
            combat.TakeDamage(10);

            Destroy(gameObject);
        }
    }
}

Esto hará que la health (salud) del jugador disminuya cuando sea golpeado por una bala. Pero usted no puede ver que esto suceda en el juego. Necesitamos agregar una barra de salud simple.

  • Seleccione el prefab PlayerCube
  • Escoja el botón Add Component y agregue un nuevo script llamado HealthBar
  • Abra el script HealthBar

Esto es mucho código que utiliza el sistema anterior de GUI. Esto no es muy importante para el networking por lo que lo utilizaremos sin explicación por ahora.

using UnityEngine;
using System.Collections;

public class HealthBar : MonoBehaviour 
{
    GUIStyle healthStyle;
    GUIStyle backStyle;
    Combat combat;

    void Awake()
    {
        combat = GetComponent<Combat>();
    }

    void OnGUI()
    {
        InitStyles();

        // Draw a Health Bar

        Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
        
        // draw health bar background
        GUI.color = Color.grey;
        GUI.backgroundColor = Color.grey;
        GUI.Box(new Rect(pos.x-26, Screen.height - pos.y + 20, Combat.maxHealth/2, 7), ".", backStyle);
        
        // draw health bar amount
        GUI.color = Color.green;
        GUI.backgroundColor = Color.green;
        GUI.Box(new Rect(pos.x-25, Screen.height - pos.y + 21, combat.health/2, 5), ".", healthStyle);
    }

    void InitStyles()
    {
        if( healthStyle == null )
        {
            healthStyle = new GUIStyle( GUI.skin.box );
            healthStyle.normal.background = MakeTex( 2, 2, new Color( 0f, 1f, 0f, 1.0f ) );
        }

        if( backStyle == null )
        {
            backStyle = new GUIStyle( GUI.skin.box );
            backStyle.normal.background = MakeTex( 2, 2, new Color( 0f, 0f, 0f, 1.0f ) );
        }
    }
    
    Texture2D MakeTex( int width, int height, Color col )
    {
        Color[] pix = new Color[width * height];
        for( int i = 0; i < pix.Length; ++i )
        {
            pix[ i ] = col;
        }
        Texture2D result = new Texture2D( width, height );
        result.SetPixels( pix );
        result.Apply();
        return result;
    }
}
  • Guarde el proyecto
  • Construya y Corra el juego y mire la barra de salud en el objeto jugador
  • Si un jugador le dispara a otro ahorita, la salud va a disminuir en ese cliente particular, pero no en otros clientes.

Estado del Jugador (Health (salud) Networked (en red))

Los cambios a la salud están siendo aplicados ahora en todo lado - independientemente del cliente y el anfitrión. Esto permite que la salud se vea diferente en los diferentes jugadores. La salud se debe solamente aplicar en el servidor y los cambios replicados a los clientes. Nosotros llamamos esto “server authority” (autoridad del servidor) para la salud.

  • Abra el script Combat
  • Cambie el script a NetworkBehaviour
  • Haga que health sea una [SyncVar]
  • Agregue isServer check a TakeDame, para que solo sea aplicado en el servidor

Para más información acerca de SyncVars, ver State Synchronization.

using UnityEngine;
using UnityEngine.Networking;

public class Combat :  NetworkBehaviour 
{
    public const int maxHealth = 100;

    [SyncVar]
    public int health = maxHealth;

    public void TakeDamage(int amount)
    {
        if (!isServer)
            return;

        health -= amount;
        if (health <= 0)
        {
            health = 0;
            Debug.Log("Dead!");
        }
    }
}

Muerte y Respawning

Actualmente, nada sucede cuando la salud de un jugador es cero excepto un mensaje largo. Para hacerlo más juego, cuando la salud sea cero, el jugador debería ser tele-transportado de-vuelta a la ubicación inicial con salud completa.

  • Abra el script Combat
  • Agregue una función [ClientRpc] para respawn el objeto jugador. Para más información ver Networked Actions.
  • Llame a la función de reaparición en el servidor cuando la salud llegue a cero
using UnityEngine;
using UnityEngine.Networking;

public class Combat :  NetworkBehaviour 
{
    public const int maxHealth = 100;

    [SyncVar]
    public int health = maxHealth;

    public void TakeDamage(int amount)
    {
        if (!isServer)
            return;

        health -= amount;
        if (health <= 0)
        {
            health = maxHealth;

            // called on the server, will be invoked on the clients
            RpcRespawn();
        }
    }

    [ClientRpc]
    void RpcRespawn()
    {
        if (isLocalPlayer)
        {
            // move back to zero location
            transform.position = Vector3.zero;
        }
    }
}

En este juego, el cliente controla la posición del objeto jugador - el objeto jugador tiene “local authority” (autoridad local) en el cliente. Si el servidor justamente configuro la posición a la posición inicial, esta sería anulada por la del cliente, ya que el cliente tiene autoridad. Para evitar esto, el servidor le dice al cliente dueño que mueva el objeto jugador a la posición inicial.

  • Construya y ejecute el juego
  • Mueva los objetos jugador lejos de la posición inicial
  • Dispare balas a un jugador mientras su salud llega a cero
  • El objeto jugador debería tele-transportarse a la posición inicial.

Objetos No-Jugador

Mientras los objetos jugador son generados cuando el cliente se conectada al host (anfitrión), la mayoría de juegos tienen objetos no jugadores que existen en el mundo del juego, tal como enemigos. En esta sección un spawner (generador) es agregado y crea objetos no jugador que pueden ser disparados.

  • Del menú GameObject cree un nuevo game object vacío
  • Re-nombre este objeto a “EnemySpawner”
  • Seleccione el objeto EnemySpawner
  • Oprima el botón Add Component y agregue un nuevo NetworkIdentity al objeto
  • En el NetworkIdentity oprima la casilla de verificación “Server Only”. Esto hace que el spawner (generador) no sea enviado a los clientes.
  • Oprima el botón Add Component y cree un nuevo script llamado “EnemySpawner”
  • Edite el nuevo script
  • Vuélvalo un NetworkBehaviour
  • Implemente la función virtual OnStartServer para crear los enemigos
using UnityEngine;
using UnityEngine.Networking;

public class EnemySpawner : NetworkBehaviour {

    public GameObject enemyPrefab;
    public int numEnemies;

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

            var rotation = Quaternion.Euler( Random.Range(0,180), Random.Range(0,180), Random.Range(0,180));

            var enemy = (GameObject)Instantiate(enemyPrefab, pos, rotation);
            NetworkServer.Spawn(enemy);
        }
    }
}

Ahora cree un prefab Enemy:

  • Del menú GameObject cree una nueva Capsule (cápsula).
  • Re-nombre el objeto a “Enemy”
  • Oprima el botón Add Component y agregue un componente NetworkIdentity al Enemy (enemigo)
  • Oprima el botón Add Component y agregue el component NetworkTransform al Enemy
  • Arrastre el objeto Enemy a la vista Asset para crear un prefab
  • Debería haber un prefab asset llamado “Enemy” ahora
  • Borre el objeto Enemy de la escena
  • Seleccione el prefab Enemy
  • Oprima el botón Add Component y agregue el script Combat al Enemy
  • Oprima el botón Add Component y agregue el script HealthBar al Enemy
  • Seleccione el NetworkManager y en Spawn Info agregue un nuevo prefab spawnable (generador)
  • Configure el nuevo prefab spawn al prefab Enemy

El script bullet está configurado para que solamente le funcione a los jugadores. Ahora actualice el script bullet para trabajar con cualquier objeto que tenga el script Combat adjunto:

  • Abra el script Bullet
  • Cambie la detección de colisión a Combat en vez de PlayerMove:
using UnityEngine;

public class Bullet : MonoBehaviour
{
    void OnCollisionEnter(Collision collision)
    {
        var hit = collision.gameObject;
        var hitCombat = hit.GetComponent<Combat>();
        if (hitCombat != null)
        {
            hitCombat.TakeDamage(10);
            Destroy(gameObject);
        }
    }
}

Relacione el EnemySpawner con el objeto Enemy:

  • Seleccione el objeto EnemySpawner
  • Encuentre la ranura “Enemy” en el componente EnemySpawner
  • Arrastre el prefab Enemy a la ranura
  • Configure el valor numEnemies a 4

Pruebe los enemigos:

  • Construya y ejecute el juego
  • Cuando se inicie como Host (anfitrión), se deben crear cuatro enemigos en ubicaciones aleatorias
  • El jugador debe ser capaz de disparle a los enemigos, y sus saludes deben disminuir
  • Cuando el cliente se una, ellos deberían ver los enemigos en las mismas posiciones, y con los mismos valores de salud que en el servidor

Destruyendo los Enemigos

Mientras que los enemigos pueden ser disparados por balas y la salud de cada uno disminuye de acuerdo a esto, estos respawn (se generan) como jugadores. Los enemigos deben ser destruidos cuando su salud alcance en cero en vez de volver a ser generados.

  • Abra el script Combat
  • Agregue una variable “destroyOnDeath”
  • Revise destroyOnDeath cuando la salud alcance cero
using UnityEngine;
using UnityEngine.Networking;

public class Combat :  NetworkBehaviour 
{
    public const int maxHealth = 100;
    public bool destroyOnDeath;

    [SyncVar]
    public int health = maxHealth;

    public void TakeDamage(int amount)
    {
        if (!isServer)
            return;

        health -= amount;
        if (health <= 0)
        {
            if (destroyOnDeath)
            {
                Destroy(gameObject);
            }
            else
            {
                health = maxHealth;

                // called on the server, will be invoked on the clients
                RpcRespawn();
            }
        }
    }

    [ClientRpc]
    void RpcRespawn()
    {
        if (isLocalPlayer)
        {
            // move back to zero location
            transform.position = Vector3.zero;
        }
    }
}

  • Seleccione el prefab Enemy
  • Configure la casilla de verificación destroyOnDeath a true para Enemy

Ahora el enemy será destruido cuando su salud alcance cero, pero los jugadores se volverán a generan.

Posiciones de spawn (generación) para los jugadores

Los jugadores actualmente todos aparecen en el punto cero cuando fueron creados. Esto significa que potencialmente están el uno encima del otro. El jugador debe spawn (generarse) en diferentes ubicaciones. El componente NetworkStartPosition puede ser usado para hacer esto.

  • Cree un nuevo GameObject vacío

  • Re-nombre el objeto a “Pos1”

  • Oprima el botón Add Component y agregue el componente NetworkStartPosition

  • Mueva el objeto Pos1 a la posición (–3,0,0)

  • Cree un segundo GameObject vacío

  • Re-nombre el objeto a “Pos2”

  • Oprima el botón Add Component y agregue el componente NetworkStartPosition

  • Mueva el objeto Pos2 a la posición (3,0,0)

  • Encuentre el NetworkManger y seleccionelo.

  • Abra el desplegable “Spawn Info”

  • cambie el “Player Spawn Method” a “Round Robin”

  • Construya y ejecute el juego

  • Los objetos jugadores deberían ser creados en las ubicaciones de los objetos Pos1 y Pos2 en vez de cero.

Conceptos del Sistema de Red
Utilizando el NetworkManager (Administrador de red)