Catégories
Autres

Un peu de programmation avec Unity (Les Stretch Goals du Projet Stealth) 1/5

Changement radical dans ce blog, moins de design plus de code ! Les récents tutoriaux mis en place par Unity pour tirer parti des nouvelles fonctionnalités de ses outils sont du pain béni pour quiconque souhaite s’y mettre sérieusement. Ils sont -la plupart du temps- accessibles, le narrateur a une diction impeccable, et le tout se fait pas à pas, sans brûler d’étape. Le tutorial sur l’infiltration est particulièrement exemplaire: il traite des nouveaux concepts introduits par la version 4 d’Unity (les arbres animations avec Mecanim) tout en rappelant les fondamentaux (comment baker ses lightmaps, utiliser le navmesh, etc).

Unity Project Stealth
Unity Project Stealth - cliquez pour accéder au tutorial

A la fin des tutos standards, il y a quelques exercices à faire pour aller un peu plus loin. Étant donné qu’il ne semble pas y avoir les solutions sur Internet, j’ai décidé de les mettre ici. N’étant pas une brute en code, la qualité de mes algos laissera sûrement à désirer . Je compte sur vous pour me corriger dans les commentaires :]

Exercice 1: Gérer le gamepad

Faut-il de nouvelles entrées dans l’Input Manager – si oui lesquelles ?

Il faut autant de nouvelles entrées dans le Manager qu’il en existe.Il s’agit de dupliquer les contrôles clavier pour leur donner un équivalent au gamepad.

– Ouvrir l’Input Manager: Edit > Project Settings > Input
– Mettez le paramètre Size à 10.
– Ajoutez les nouvelles entrées en prenant soin d’utiliser les mêmes noms que pour leurs équivalents clavier. Ça limitera le refactoring du code.
– Puis suivez les images.

Input Manager: Gestion du stick gauche (axe X puis axe Y)
Input Manager: Gestion du stick gauche (axe X puis axe Y)

Un paramètre important est la Dead Zone: ça correspond à l’imprécision du joystick au repos. En effet, quand on lâche le stick, pour des raisons mécaniques le signal émis ne revient pas forcément à zéro. Pour le gamepad Xbox 360 0.3 est une valeur assez conservative. Ça veut dire qu’Unity va commencer à traiter l’input seulement quand sa valeur dépassera +/-0.3. La valeur dépend énormément du hardware: sur un bon pad neuf on peut descendre à 0.15. Sur un vieux pad dégueulasse je vous laisse imaginer…

Gestion des autres boutons (gamepad X360)
Gestion des autres boutons (gamepad X360) - cliquer pour afficher en taille réelle

Dans le script PlayerMovement – Si les axes ne sont plus binaires mais analogiques, l’allocation de la vitesse du joueur doit-elle rester binaire ?

Non, on va directement l’indexer sur la valeur de l’input.

La valeur des deux float horizontal et vertical est inscrite dans [-1;1]. Ça nous arrange beaucoup. On n’a plus qu’à en retirer la valeur absolue en utilisant Mathf.Abs() pour additionner deux valeurs positives qui seront grosso modo comprises entre 0 et 1. Il ne nous reste qu’à multiplier ce résultat par la valeur maximale de déplacement extraite de l’anim de course (ici, 5.6f). Si le résultat déborde un peu, ça n’est pas trop grave, notre blendtree ignore par défaut tout ce qui est au-dessus de 5.6f.

Blendtree Locomotion
Blendtree Locomotion

On va donc remplacer:

[code lang= »csharp »]anim.SetFloat(hash.speedFloat, 5.6f, speedDampTime, Time.deltaTime);[/code]

par:

[code lang= »csharp »]anim.SetFloat(hash.speedFloat, (5.6f * (Mathf.Abs (horizontal) + Mathf.Abs (vertical))), speedDampTime, Time.deltaTime);[/code]

Dans le Animator Controller – si la vitesse n’est plus binaire, on va devoir blender entre la marche et la course.

Il n’y a rien à faire. L’état Locomotion permet déjà de blender entre ces deux animations.

Si la valeur des axes du gamepad nous permettent de déterminer notre vitesse, a-t’on encore besoin du paramètre sneak ?

En effet, on peut ajouter l’animation de sneak à notre blendtree Locomotion et supprimer ce paramètre. Si le joueur presse légèrement le stick vers l’avant, il sera automatiquement en mode Sneak.

– Ouvrez l’Animator et entrez dans l’état Locomotion. Ajoutez une nouvelle Motion de type Motion Field sous le blendtree Locomotion.

Ajouter le motion field
Ajouter le motion field

– Drag & Droppez l’anim de Sneak qui est dans Animations > Humanoid > humanoid_sneak > Sneak dans le Motion que vous venez de créer

– Montez l’animation en haut de la liste, on va en effet la jouer quand la valeur de Speed sera la plus faible.

Drag & Drop en haut de la liste
Drag & Drop en haut de la liste

– Changez les valeurs de seuil qui sont par défaut indexées sur la vitesse réelle des animations: mettez le Sneak à 1, le Walk à 8 et le Run à 10.

Les seuils de blend
Les seuils de blend

– On peut désormais supprimer l’état Sneak, le booléen qui lui est lié dans le Base Layer de notre arbre d’animation. Attention à également supprimer la référence à ce bool dans la transition qui va de Idle à Locomotion !

Notre arbre simplifié
Notre arbre simplifié

– Dans notre code, on peut désormais supprimer la référence au booléen Sneak, ainsi que de réajuster les transitions en fonction du nouveau seuil que l’on a appliqué

Dans PlayerMovement.cs

FixedUpdate()

[code lang= »csharp »]
void FixedUpdate ()
{
// Cache the inputs.
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
MovementManagement(h, v);
}[/code]

MovementManagement()

[code lang= »csharp »]
void MovementManagement (float horizontal, float vertical)
{
// Dés qu’on sort de la deadzone
if(horizontal != 0f || vertical != 0f)
{
// … on applique notre vitesse en fonction de l’input reçu
Rotating(horizontal, vertical);
anim.SetFloat(hash.speedFloat, (10f * (Mathf.Abs (horizontal) + Mathf.Abs (vertical))), speedDampTime, Time.deltaTime);
}
else
// Sinon on s’arrête.
anim.SetFloat(hash.speedFloat, 0);
}
[/code]

Si le paramètre sneak est désormais inutile, comment faire en sorte que les ennemis puissent entendre ou non nos bruits de pas ?

Dans EnemySight.cs, on va simplement récupérer la valeur de blend (Speed) de l’avatar. Si sa valeur est supérieure à 8, alors on déclenche le comportement IA de détection.

[code lang= »csharp »]void OnTriggerStay (Collider other)
{
// […]

int playerLayerOneStateHash = playerAnim.GetCurrentAnimatorStateInfo(1).nameHash;
float playerLocomotionValue = playerAnim.GetFloat(hash.speedFloat);

// Si le joueur est en train de courir (seuil > 8f) ou en train de crier…
if(playerLocomotionValue > 8f || playerLayerOneStateHash == hash.shoutState)
{
// […]
}
}[/code]

Ceci conclut le premier exercice. A suivre !

Une réponse sur « Un peu de programmation avec Unity (Les Stretch Goals du Projet Stealth) 1/5 »

Répondre à MathieuFROG Annuler la réponse

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *