Menu
CoddyTech

Un script base para enemigos

Parte de la sección Arquitectura de juegos en Unity del Journey de Unity de Coddy. Lección 2 de 64.

En C#, una clase puede derivar de otra: class Ghost : Enemy obtiene todos los campos y métodos de Enemy y añade los suyos. Un método que la clase base marca como virtual puede reemplazarse en la subclase con override, y base.Describe() ejecuta la versión de la clase base desde dentro de la nueva. En C# sencillo:

class Enemy
{
    protected int hp = 3;

    public virtual string Describe()
    {
        return "Enemy with " + hp + " hp";
    }
}

class Ghost : Enemy
{
    public override string Describe()
    {
        return base.Describe() + ", see-through";
    }
}

Describe() de un Ghost devuelve Enemy with 3 hp, see-through. protected significa que Enemy y sus subclases pueden usar hp, pero las demás clases no.

En Unity, los enemigos comparten la mayor parte del código: puntos de vida, una velocidad y una forma de moverse. Ese código reside en una clase base que deriva de MonoBehaviour, y cada tipo de enemigo deriva de ella. Este Enemy establece sus puntos de vida en Start y camina hacia donde está orientado en Update, y un Ghost modifica el inicio para moverse el doble de rápido:

public class Enemy : MonoBehaviour
{
    public int maxHp = 3;
    public float speed = 2f;
    protected int hp;

    protected virtual void Start()
    {
        hp = maxHp;
    }

    protected virtual void Update()
    {
        transform.Translate(Vector3.forward * speed * Time.deltaTime);
    }
}
public class Ghost : Enemy
{
    protected override void Start()
    {
        base.Start();
        speed *= 2f;
    }
}

Ghost hereda los campos, así que el Inspector muestra maxHp y speed en un Ghost, y también hereda Update, por lo que camina sin tener su propio Update. hp es protected: Enemy y sus subclases pueden usarlo, pero otros scripts no.

Unity encuentra Start y Update por su nombre, sea cual sea su nivel de acceso, y llama al de la clase más derivada. Si el Start de Enemy fuera un void Start() privado y Ghost declarara el suyo, Unity llamaría solo al de Ghost: el de Enemy nunca se ejecutaría y hp permanecería en 0 sin que se produjera ningún error. Declarar los mensajes de la clase base como protected virtual hace que esto sea C# explícito: la subclase escribe override, y base.Start() ejecuta la parte de la clase base en el punto donde lo llamas. Si omites la llamada, se omite la parte de la clase base, que es cómo una subclase reemplaza un paso en lugar de añadirle algo.

challenge icon

Desafío

Fácil

Haz que Golem y Wasp ejecuten primero la parte de Enemy y luego la suya.

  1. En Enemy, escribe protected virtual antes de void Start() y void Update().
  2. En Golem, haz que sea protected override void Start() con base.Start(); como primera línea.
  3. En Wasp, haz que sea protected override void Update() con base.Update(); como primera línea.

Pulsa «Jugar»: el gólem avanza con los puntos de vida al máximo, y la avispa zigzaguea mientras avanza. Después, pulsa «Comprobar».

Pruébalo tú mismo

using UnityEngine;

// Lo que todos los monstruos tienen en común.
public class Enemy : MonoBehaviour
{
    public int maxHp = 4;
    public float speed = 1.5f;

    protected int hp;
    protected Vector3 spawnPoint;

    void Start()
    {
        hp = maxHp;
        spawnPoint = transform.position;
    }

    void Update()
    {
        // avanza hacia el castillo por el eje z en sentido descendente
        transform.position += Vector3.back * speed * Time.deltaTime;
    }
}

Todas las lecciones de Arquitectura de juegos en Unity

Practica por tu cuenta: Playground de Unity