Menu
CoddyTech

Transitions

Fait partie de la section Architecture de jeu dans Unity du Journey Unity de Coddy. Leçon 30 sur 50.

Qui décide du moment où l’état change ? Demander au propriétaire revient à remettre toutes les règles dans un seul Update, comme le faisait le switch. En général, chaque état sait comment en sortir : dans son Tick, il vérifie sa condition et demande à la machine de passer à l’état suivant. Cette bombe attend que le joueur s’approche, puis brûle sa mèche et revient à l’attente si le joueur s’éloigne en courant :

public class Bomb : MonoBehaviour
{
    public Transform player;
    public StateMachine machine = new StateMachine();
    public IState idle;
    public IState fuse;

    void Start()
    {
        idle = new IdleState(this);
        fuse = new FuseState(this);
        machine.ChangeState(idle);
    }

    void Update() { machine.Tick(); }

    public bool PlayerNear()
    {
        return Vector3.Distance(transform.position, player.position) < 3f;
    }
}

public class IdleState : IState
{
    private Bomb bomb;
    public IdleState(Bomb bomb) { this.bomb = bomb; }

    public void Enter() { }
    public void Exit() { }

    public void Tick()
    {
        if (bomb.PlayerNear()) bomb.machine.ChangeState(bomb.fuse);
    }
}

public class FuseState : IState
{
    private Bomb bomb;
    private float timer;
    public FuseState(Bomb bomb) { this.bomb = bomb; }

    public void Enter() { timer = 2f; }
    public void Exit() { }

    public void Tick()
    {
        if (!bomb.PlayerNear())
        {
            bomb.machine.ChangeState(bomb.idle);
            return;
        }
        timer -= Time.deltaTime;
        if (timer <= 0f)
        {
            Debug.Log("Boom!");
            Object.Destroy(bomb.gameObject);
        }
    }
}

Chaque état reçoit la bombe dans son constructeur et accède par son intermédiaire à la machine, à la vérification de proximité du joueur et aux autres états. La bombe crée chaque état une seule fois, dans Start, donc un état n’en crée jamais un autre avec new : deux états qui se créeraient l’un l’autre dans leurs constructeurs boucleraient jusqu’au dépassement de la pile. Le Update de la bombe ne fait que faire avancer la machine, et les règles se trouvent dans les états auxquels elles appartiennent : la mèche de 2 secondes ne concerne que FuseState.

ChangeState exécute immédiatement Exit de FuseState et Enter de IdleState, mais le reste du Tick de FuseState s’exécuterait quand même après l’appel. Le return l’arrête ; sinon, la mèche brûlerait une frame de plus alors que l’état est déjà terminé. Destroy s’écrit Object.Destroy : un MonoBehaviour en hérite de la classe Object de Unity, et une classe ordinaire doit préciser le nom de la classe.

challenge icon

Défi

Moyen

Une dionée se referme sur quiconque s’en approche. Flytrap.cs est prêt : il crée la machine et les trois états (les champs publics open, snap et chew), démarre dans Open et fait avancer la machine à chaque image, et PlayerInReach() indique si le joueur est à moins de 2 unités sur le sol. Dans FlytrapStates.cs, chaque Enter est déjà écrit (les couleurs, les minuteries, le journal Chomp!). Écris les transitions dans le Tick de chaque état :

  • Open : lorsque le joueur est à portée, le piège se referme.
  • Snap dure 0.5 seconde. Ensuite, le piège mâche si le joueur est toujours à portée, et se rouvre s’il a réussi à s’échapper.
  • Chew dure 3 secondes, peu importe qui se trouve à proximité, puis le piège se rouvre.

Les flèches permettent de déplacer le Player. Appuie sur Play, avance dans le piège, puis essaie de l’éviter, et enfin appuie sur Check.

Essayez vous-même

using UnityEngine;

public class OpenState : IState
{
    private Flytrap trap;

    public OpenState(Flytrap trap)
    {
        this.trap = trap;
    }

    public void Enter()
    {
        trap.Paint(new Color(0.3f, 0.8f, 0.2f));
    }

    public void Tick()
    {
        // Se refermer lorsque le joueur est à portée
    }

    public void Exit()
    {
    }
}

public class SnapState : IState
{
    private Flytrap trap;
    private float timer;

    public SnapState(Flytrap trap)
    {
        this.trap = trap;
    }

    public void Enter()
    {
        timer = 0f;
        trap.Paint(new Color(1f, 0.55f, 0.1f));
    }

    public void Tick()
    {
        // Après 0.5 secondes : mâcher si le joueur est toujours à portée, sinon s’ouvrir à nouveau
    }

    public void Exit()
    {
    }
}

public class ChewState : IState
{
    private Flytrap trap;
    private float timer;

    public ChewState(Flytrap trap)
    {
        this.trap = trap;
    }

    public void Enter()
    {
        timer = 3f;
        trap.Paint(new Color(0.5f, 0.05f, 0.1f));
        Debug.Log("Chomp!");
    }

    public void Tick()
    {
        // Après 3 secondes : s’ouvrir à nouveau
    }

    public void Exit()
    {
    }
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Architecture de jeu dans Unity