Menu
CoddyTech

Una máquina de estados

Parte de la sección Arquitectura de juegos en Unity del Journey de Unity de Coddy. Lección 29 de 50.

El método SetState del faro sería igual en todos los objetos con estados: una torreta, un enemigo, una puerta. Ese código puede estar en su propia clase, una máquina de estados, que mantiene el estado actual y lo cambia. Cada objeto crea una máquina y la llama, en lugar de repetir el código:

public class StateMachine
{
    public IState Current { get; private set; }

    public void ChangeState(IState next)
    {
        Current?.Exit();
        Current = next;
        Current.Enter();
    }

    public void Tick()
    {
        Current?.Tick();
    }
}

public class Beacon : MonoBehaviour
{
    public Renderer lamp;
    private StateMachine machine = new StateMachine();
    private IState blink;
    private IState steady;

    void Start()
    {
        blink = new BlinkState(lamp);
        steady = new SteadyState();
        machine.ChangeState(steady);
    }

    void Update()
    {
        if (Keyboard.current.spaceKey.wasPressedThisFrame) machine.ChangeState(machine.Current == steady ? blink : steady);
        machine.Tick();
    }
}

El primer ChangeState no tiene ningún estado del que salir: Current es null, y ?. omite la llamada a Exit. La sección 1 advertía que ?. no detecta el falso null de Unity; eso se refiere a los objetos de Unity destruidos, y los estados son objetos C# normales, así que ?. es seguro aquí. Current tiene un private set, así que ningún script puede cambiar el estado sin pasar por ChangeState y sus métodos Exit y Enter.

El orden dentro de ChangeState importa siempre que dos estados afecten al mismo objeto. Exit deshace lo que cambió el estado anterior y, después, Enter configura el nuevo, así que el nuevo estado tiene la última palabra. Si el método Enter de un DarkState apagara la lámpara y se ejecutara antes que Exit de BlinkState, ese Exit volvería a encender la lámpara en el estado oscuro. StateMachine también es una clase normal: el faro, una torreta y un enemigo crean cada uno su propia instancia con new y llaman a su Tick desde su Update.

challenge icon

Desafío

Intermedio

Mantén presionada la barra espaciadora para moverte sigilosamente. WalkState y SneakState ya están listos en PlayerStates.cs: sus métodos Enter y Exit registran lo que sucede (Walk: enter, Sneak: exit...), y sus métodos Tick llaman a Move() del jugador. Escribe la máquina que los ejecuta.

  • En StateMachine.cs, escribe una clase simple StateMachine con una propiedad pública Current que solo la máquina pueda establecer, un método ChangeState(IState next) que ejecute Exit del estado anterior y después Enter del nuevo estado, y un método Tick() que ejecute Tick del estado actual.
  • El jugador solicita su estado en cada fotograma, así que llamar a ChangeState con el estado que ya es el actual no hace nada: ni Exit ni Enter.
  • En Player.cs, añade un campo StateMachine llamado machine. En Start, crea la máquina y ambos estados (cada uno recibe al jugador) y empieza caminando. En Update, cambia a moverse sigilosamente mientras se mantenga presionada la barra espaciadora y a caminar en caso contrario; después, actualiza la máquina.

Presiona Play, camina, mantén presionada la barra espaciadora y sigue caminando; luego, presiona Check.

Pruébalo tú mismo

// StateMachine: Current, ChangeState y Tick
quiz iconPonte a prueba

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