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 50.
Los enemigos comparten la mayor parte de su código: puntos de vida, una velocidad y una forma de moverse. Ese código puede estar 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, mientras que un Ghost cambia 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; otros scripts no.
Unity encuentra Start y Update por su nombre, independientemente de 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 explícito en C#: 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; así es como una subclase reemplaza un paso en vez de añadirle algo.
Desafío
FácilLos monstruos marchan hacia el castillo. Enemy.cs contiene lo que comparten: Start establece hp en maxHp y recuerda spawnPoint, y Update hace que el monstruo marche por el eje z a speed. Grunt es un Enemy normal y funciona. Dos tipos añaden un paso propio, y cada uno pierde la parte de Enemy:
Golem: su Start hace que el golem sea 1.5 veces más grande y registraThe golem wakes up, pero suhppermanece en 0, porque Unity ejecuta el Start de Golem y nunca el de Enemy.Wasp: su Update lo mueve 1 unidad a cada lado despawnPoint.x, pero zigzaguea en el sitio, porque Unity ejecuta el Update de Wasp y nunca el de Enemy.
Haz que Start y Update de Enemy sean protected virtual, y sobrescríbelos en Golem y Wasp para que cada uno ejecute primero la parte de Enemy y después la suya. Pulsa Play y después Check.
Pruébalo tú mismo
using UnityEngine;
// Lo que comparten todos los monstruos.
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 descendente
transform.position += Vector3.back * speed * Time.deltaTime;
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Arquitectura de juegos en Unity
1Componentes, no jerarquías
Componentes pequeñosUn script base para enemigosComponentes abstractosComponentes que trabajan juntosRepaso: torreta modular4Datos serializados
Clases serializablesListas en el InspectorEnumeraciones en el InspectorRepaso: tabla de botín7Máquinas de estados
Estados como clasesUna máquina de estadosTransicionesCerebros de enemigosRepaso: estados de puertas10Proyecto: Superviviente de la arena
El héroeTipos de enemigos2Interfaces en Unity
IDamageableInterfaces y TryGetComponentGetComponentsRepaso: tecla de interacción5ScriptableObjects
Recursos de datosEstadísticas de armasConfiguración compartidaOleadas como datosRepaso: base de datos de objetos