Estados como clases
Parte de la sección Arquitectura de juegos en Unity del Journey de Unity de Coddy. Lección 35 de 64.
El cambio basado en un enum de la sección 3 mantiene el trabajo de cada estado en un solo Update. Esto deja de ser escalable cuando los estados tienen sus propios datos: un temporizador que solo usa un estado acaba como campo de MonoBehaviour, junto a los campos de todos los demás estados, y cada caso debe acordarse de restablecer lo que utiliza. El patrón de estados de C# da a cada estado su propia clase, y todas las clases implementan una interfaz. Esta baliza vial parpadea o permanece encendida, y la barra espaciadora alterna entre los dos estados:
public interface IState
{
void Enter();
void Tick();
void Exit();
}
public class BlinkState : IState
{
private Renderer lamp;
private float timer;
public BlinkState(Renderer lamp)
{
this.lamp = lamp;
}
public void Enter() { timer = 0f; }
public void Tick()
{
timer += Time.deltaTime;
if (timer >= 0.5f)
{
timer = 0f;
lamp.enabled = !lamp.enabled;
}
}
public void Exit() { lamp.enabled = true; }
}
public class SteadyState : IState
{
public void Enter() { }
public void Tick() { }
public void Exit() { }
}
public class Beacon : MonoBehaviour
{
public Renderer lamp;
private IState blink;
private IState steady;
private IState current;
void Start()
{
blink = new BlinkState(lamp);
steady = new SteadyState();
SetState(steady);
}
void Update()
{
if (Keyboard.current.spaceKey.wasPressedThisFrame) SetState(current == steady ? blink : steady);
current.Tick();
}
void SetState(IState next)
{
if (current != null) current.Exit();
current = next;
current.Enter();
}
}Los estados son clases normales de C#, no MonoBehaviours. Los creas con new y les pasas lo que necesitan mediante el constructor; en este caso, el Renderer de la lámpara, porque no son componentes y no pueden llamar a GetComponent ni mostrar campos en el Inspector. Unity tampoco llama a sus métodos: Beacon es el MonoBehaviour, así que su Update llama a current.Tick() en cada fotograma.
El timer pertenece únicamente a BlinkState, y su Enter lo establece en 0 cada vez que la baliza empieza a parpadear. Exit se encarga de la limpieza cuando termina el estado: la barra espaciadora puede pulsarse mientras la lámpara está apagada, y Exit vuelve a encenderla, así que SteadyState nunca empieza con la lámpara apagada. SetState ejecuta Exit del estado anterior y después Enter del nuevo estado. Un tercer estado, como un pulso lento, sería una clase más, y el Update de Beacon no cambiaría.
Desafío
IntermedioEscribe el estado de escaneo de la torreta.
- En
IState.cs, declarapublic interface IStateconvoid Enter();,void Tick();yvoid Exit();. - En
TurretStates.cs, escribeScanState : IState, con la cabeza como argumento. Enter: ángulo 0, cabezaColor.green. Tick: mueve la cabeza de un lado a otro, entre los ángulos y locales del eje y-45y45, a90grados por segundo. Turret: inicia uno enStarty actualízalo enUpdate.
Pulsa «Jugar»: la cabeza verde se mueve de un lado a otro. Después, pulsa «Comprobar».
Pruébalo tú mismo
using UnityEngine;
// ScanState
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 modularRepaso: cañón doble4Datos serializados
Clases serializablesListas en el InspectorEnumeraciones en el InspectorRepaso: tabla de botínRepaso: sortear el botín7Máquinas de estados
Estados como clasesEl estado de alertaUna máquina de estadosTransicionesCerebros enemigosEl caballero atacaRepaso: estados de puertas2Interfaces en Unity
IDamageableInterfaces y TryGetComponentGetComponentsRepaso: Tecla de interacciónRepaso: El más cercano al alcance5ScriptableObjects
Activos de datosEstadísticas de armasConfiguración compartidaGuardar el vientoOleadas como datosRepaso: base de datos de objetosRepaso: comprar en la tienda3Eventos
Eventos de C# en UnitySuscribirse en OnEnableCampos UnityEventLos eventos controlan la interfazRepaso: ventana emergente de logrosRepaso: temporizador de la ventana emergentePractica por tu cuenta: Playground de Unity