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).
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.

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…
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.

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.

– 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.
– 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.

– 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 !

– 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 »
C’est une super initiative !