Contenu du cours
Jeu de Combat dans Unity
Jeu de Combat dans Unity
État d'Attaque
public class AttackState : State
{
string attackStateName;
bool isAttacking;
Animator animator;
Transform transform;
float range;
int damage;
LayerMask playerLayer;
public AttackState(Transform t, Animator animator, LayerMask playerLayer, string attackStateName, int damage, float range = 2.1f)
{
this.animator = animator;
this.attackStateName = attackStateName;
this.range = range;
transform = t;
this.damage = damage;
this.playerLayer = playerLayer;
}
public override void StartState()
{
isStateFinished = false;
animator.SetBool(attackStateName, true);
isAttacking = false;
}
public override void EndState()
{
animator.SetBool(attackStateName, false);
}
public override void UpdateState(float deltaTime)
{
Attack();
}
public override void StartAction()
{
isAttacking = true;
}
public override void FinishMovement()
{
isAttacking = false;
}
void Attack()
{
if (!isAttacking) return;
RaycastHit2D rayCastHit = Physics2D.Raycast(transform.position, Vector2.right * transform.localScale.x, range, playerLayer);
if (rayCastHit)
{
if (rayCastHit.transform.TryGetComponent(out IGetAttacked getAttacked))
{
getAttacked.GetAttacked(damage);
isAttacking = false;
}
}
}
}
Explication de la classe AttackState
La classe AttackState
représente un état spécifique qui gère le comportement d’attaque de l’ennemi. Cette classe hérite de la classe State
et inclut des méthodes pour démarrer, mettre à jour et terminer l’état d’attaque, ainsi que pour gérer l’action d’attaque.
Définition de la classe et variables membres
Définition de la classe :
public class AttackState : State
;
Cette classe hérite de la classe State
, ce qui signifie qu’elle doit implémenter les méthodes abstraites définies dans State
.
Variables membres :
string attackStateName;
Nom de l’état d’attaque utilisé dans l’Animator.
bool isAttacking;
Indicateur pour savoir si l’ennemi est en train d’attaquer.
Animator animator;
Contrôle les animations.
Transform transform;
Transform de l’ennemi, utilisé pour le positionnement et le raycasting.
float range;
Portée de l’attaque.
int damage;
Dégâts infligés par l’attaque.
LayerMask playerLayer;
Masque de couche utilisé pour identifier le joueur.
Constructeur
Le constructeur initialise l'AttackState
avec les composants nécessaires : un Transform
pour la position, un Animator
pour les animations, un masque de couche pour identifier le joueur, le nom de l'état d'attaque, la valeur des dégâts et la portée d'attaque. Il assigne ces valeurs aux variables membres correspondantes.
Méthode StartState
Cette méthode définit isStateFinished
sur false
, déclenche l'animation d'attaque en définissant le paramètre booléen approprié de l'animator sur true
, et réinitialise le drapeau isAttacking
sur false
.
Méthode EndState
Cette méthode arrête l'animation d'attaque en définissant le paramètre booléen approprié de l'animator sur false
.
Méthode UpdateState
Cette méthode est appelée à chaque frame et déclenche la méthode Attack
pour effectuer l'action d'attaque.
Méthode StartAction
Cette méthode définit isAttacking
sur true
, indiquant que l'action d'attaque a commencé.
Méthode FinishMovement
Cette méthode définit isAttacking
sur false
, indiquant que l'action d'attaque est terminée.
Méthode d'Attaque
Cette méthode exécute l'action d'attaque. Si isAttacking
est true
, elle lance un rayon dans la direction vers laquelle l'ennemi fait face. Si le rayon touche un objet sur le playerLayer
, elle appelle la méthode GetAttacked
sur l'objet touché, infligeant des dégâts et mettant fin à l'action d'attaque.
Raisons de cette Approche
-
Contrôle du Comportement d'Attaque : Le drapeau
isAttacking
permet un contrôle précis du moment où l'attaque doit se produire, rendant le comportement plus réactif aux événements du jeu ; -
Exécution Dynamique de l'Attaque : En mettant à jour en continu l'état d'attaque de l'ennemi, le
AttackState
garantit que l'ennemi peut attaquer le joueur de manière précise et dynamique ; -
Intégration de l'Animation : L'utilisation des paramètres de l'animateur assure que les animations de l'ennemi sont correctement synchronisées avec ses attaques, offrant une expérience fluide et réaliste.
Fonctionnement dans le Contexte
Entrée dans l'État d'Attaque : Lorsque l'ennemi entre dans le AttackState
, la méthode StartState
est appelée, déclenchant l'animation d'attaque et réinitialisant le drapeau isAttacking
.
Pendant l'Attaque : La méthode UpdateState
est appelée à chaque frame. Elle déclenche la méthode Attack
pour vérifier si une attaque doit avoir lieu.
Début de l'Attaque : La méthode StartAction
définit isAttacking
sur true
, permettant à la méthode Attack
d'exécuter l'action d'attaque.
Exécution de l'Attaque : La méthode Attack
lance un rayon pour détecter le joueur et inflige des dégâts si le joueur est touché.
Fin de l'Attaque : La méthode FinishMovement
définit isAttacking
sur false
, arrêtant l'action d'attaque.
Sortie de l'État d'Attaque : Lorsque l'ennemi quitte le AttackState
, la méthode EndState
est appelée, arrêtant l'animation d'attaque.
En structurant le AttackState
de cette manière, nous assurons que l'ennemi peut effectuer des attaques réactives et dynamiques sur le joueur, avec des transitions fluides entre les animations et les états.
Transition de proximité :
closeTransition = new Transition(() =>
{
return (ThresholdDistance >= Mathf.Abs(transform.position.x - player.position.x));
}, new StatePourcentage(attack2, 50f), new StatePourcentage(attack1, 50f));
stateManager.AddStateTransition(idle, closeTransition);
stateManager.AddStateTransition(idle, FarAwayTransition);
stateManager.AddStateTransition(dashState, toIdleTransition);
stateManager.AddStateTransition(dashState, finishRunning);
stateManager.AddStateTransition(runState, finishRunning);
stateManager.AddStateTransition(attack2, toIdleTransition);
stateManager.AddStateTransition(attack1, toIdleTransition);
closeTransition :
Cette transition vérifie si le joueur se trouve à une certaine distance horizontale (ThresholdDistance
) de l'ennemi.
Si la condition est remplie, la transition se fait aléatoirement vers attack1
ou attack2
avec une probabilité égale (50 % chacune) ;
Exemple de code :
```csharp
closeTransition = new Transition(() =>
{
return (ThresholdDistance >= Mathf.Abs(transform.position.x - player.position.x));
}, new StatePourcentage(attack2, 50f), new StatePourcentage(attack1, 50f));
```
Ajout de closeTransition à l'état Idle :
stateManager.AddStateTransition(idle, closeTransition);
Cette ligne ajoute le closeTransition
à l'état idle
, permettant à la machine d'états de vérifier cette condition lorsque l'ennemi est à l'état idle.
Pourquoi avons-nous procédé ainsi
Le système de transition permet à l’ennemi de passer à un état d’attaque en fonction de la proximité du joueur, ce qui améliore l’engagement. L’approche probabiliste pour choisir entre différentes attaques ajoute de l’imprévisibilité, augmentant ainsi le défi et l’intérêt du jeu.
Fonctionnement dans le contexte
État d’inactivité :
Lorsque l’ennemi est dans l’état idle
, il vérifie en permanence si le joueur se trouve dans la ThresholdDistance
à l’aide de la closeTransition
.
Si le joueur est suffisamment proche, la closeTransition
se déclenche et l’ennemi passe soit à attack1
, soit à attack2
.
États d’attaque :
Une fois dans attack1
ou attack2
, l’ennemi effectue l’attaque.
Après la fin de l’attaque, la toIdleTransition
existante ramène l’ennemi à l’état idle
, prêt à vérifier à nouveau la condition de closeTransition
.
En ajoutant cette closeTransition
, nous nous assurons que l’ennemi peut engager le joueur de manière plus dynamique et imprévisible lorsque celui-ci se trouve à courte distance. Cela améliore l’expérience de jeu en rendant le comportement de l’ennemi plus réactif et captivant.
Merci pour vos commentaires !