Menu
CoddyTech

L’intelligence des ennemis

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

Le cerveau d’un ennemi est une machine à états avec un état par comportement. Cette armature se déplace entre ses postes, poursuit un joueur qui s’approche à moins de 6 unités et donne un coup d’épée une fois par seconde lorsqu’il est proche. Chaque état décide de sa propre sortie, et le squelette conserve les fonctions auxiliaires qu’ils partagent :

public class Skeleton : MonoBehaviour
{
    public Transform player;
    public Transform[] posts;
    public float speed = 2f;
    public StateMachine machine = new StateMachine();
    public IState patrol, chase, attack;

    void Start()
    {
        patrol = new PatrolState(this);
        chase = new ChaseState(this);
        attack = new AttackState(this);
        machine.ChangeState(patrol);
    }

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

    public float PlayerDistance() { return Vector3.Distance(transform.position, player.position); }

    public void WalkTo(Vector3 target)
    {
        target.y = transform.position.y;
        transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
    }
}

public class PatrolState : IState
{
    private Skeleton skel;
    private int next;
    public PatrolState(Skeleton skel) { this.skel = skel; }
    public void Enter() { }
    public void Exit() { }

    public void Tick()
    {
        if (skel.PlayerDistance() < 6f) { skel.machine.ChangeState(skel.chase); return; }
        Vector3 post = skel.posts[next].position;
        post.y = skel.transform.position.y;
        skel.WalkTo(post);
        if (skel.transform.position == post) next = (next + 1) % skel.posts.Length;
    }
}

public class ChaseState : IState
{
    private Skeleton skel;
    public ChaseState(Skeleton skel) { this.skel = skel; }
    public void Enter() { }
    public void Exit() { }

    public void Tick()
    {
        float d = skel.PlayerDistance();
        if (d > 6f) { skel.machine.ChangeState(skel.patrol); return; }
        if (d < 1.5f) { skel.machine.ChangeState(skel.attack); return; }
        skel.WalkTo(skel.player.position);
    }
}

public class AttackState : IState
{
    private Skeleton skel;
    private float cooldown;
    public AttackState(Skeleton skel) { this.skel = skel; }
    public void Enter() { cooldown = 0f; }
    public void Exit() { }

    public void Tick()
    {
        if (skel.PlayerDistance() > 1.5f) { skel.machine.ChangeState(skel.chase); return; }
        cooldown -= Time.deltaTime;
        if (cooldown <= 0f) { Debug.Log("Swing!"); cooldown = 1f; }
    }
}

Les états sont créés une seule fois et vivent aussi longtemps que le squelette, leurs champs persistent donc entre les visites. next de PatrolState conserve sa valeur après une poursuite, et le squelette continue vers le poste qu’il était en train de rejoindre. Enter ne réinitialise que ce qui doit repartir de zéro : celui de AttackState définit cooldown à 0, pour que le premier coup soit donné dès que le squelette atteint le joueur.

Tous les déplacements passent par WalkTo, qui utilise ici MoveTowards sur le transform et traverse les murs. Pour déplacer le squelette avec un Rigidbody à la place, WalkTo définit la vélocité du corps et le squelette fait avancer la machine avec FixedUpdate, où Time.deltaTime correspond au pas de la simulation physique. Les trois états ne changent pas : ils indiquent où aller, le propriétaire indique comment.

challenge icon

Défi

Moyen

Ajoute au chevalier PatrolState et ChaseState dans KnightStates.cs, en passant le chevalier à chacun d’eux.

  1. Patrouille : marche jusqu’à waypoints[next] ; à moins de 0.3, passe au suivant en bouclant, et conserve cette valeur entre les visites. À moins de sightRange, poursuis le joueur.
  2. Poursuite : marche jusqu’au joueur ; au-delà de loseRange, patrouille.
  3. Dans Knight, crée la machine et les états dans Awake, lance la patrouille dans Start et appelle Tick dans FixedUpdate.

Appuie sur « Jouer », puis approche-toi et cours. Ensuite, appuie sur « Vérifier ».

Essayez vous-même

using UnityEngine;

// PatrolState et ChaseState

Toutes les leçons de Architecture de jeu dans Unity

Entraînez-vous par vous-même : Playground Unity