Animation qui frezz ci touche enfoncer ! (Coroutine)

Pour les scripts écrits en C#
Règles du forum
Merci de respecter la NOMENCLATURE suivante pour vos TITRES de messages :

Commencez par le niveau de vos scripts
DB = Débutant
MY = Moyen
CF = Confirmé

Puis le domaine d'application
-RS = Réseau
-AL = Algorithmie

Exemple :

[DB-RS] Mouvement perso multijoueur
Répondre
UnicornMaster40
Messages : 17
Inscription : 16 Sep 2018 14:15

Animation qui frezz ci touche enfoncer ! (Coroutine)

Message par UnicornMaster40 » 22 Sep 2018 17:04

Bonjour, voici mon problème. j'ai un personnage (Dragon) qui est mon player. J'ai donc mon script pour faire c’est déplacement ainsi que les variables pour l’application de mon animator pour géré mes transitions d'animations.J'ai également ajouter une coroutine pour que lorsque que mon personnage attaque il y ait un timer de 3 seconde avant de pouvoir rejouer l'Action.

Je vous met le script utiliser par ma fonction attaque, celui de ma coroutine & Le script complet de mon player:

Script pour mon attaque:

Code : Tout sélectionner

// Pour Attaquer

        if (canAttaque = true && (Input.GetKey(inputAttaque)))
        {
            StartCoroutine(coroutAttaque());
        }
        else
        {
            animator.SetBool("attaque", false);
        }
Script de ma coroutine:

Code : Tout sélectionner

IEnumerator coroutAttaque()
    {
        print("Début de la coroutine & Player de peut plus attaquer");
        animation.Play("sj001_skill1");
        animator.SetBool("attaque", true);
        canAttaque = false;
        yield return new WaitForSeconds(3);
        canAttaque = true;
        print("Fin de la coroutine & Player peut attaquer");

    }
Script complet:

Code : Tout sélectionner

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ControlePlayer : MonoBehaviour {

    Animation animation;
    private Animator animator;
    private bool canAttaque;



    //Vitesse de déplacement
    public float flySpeed;
    public float turnSpeed;



    //Controle
    public string inputFront;
    public string inputSprint;
    public string inputBack;
    public string inputLeft;
    public string inputRight;
    public string inputAttaque;
    public string inputCamera;



    void Start()
    {
        animator = GetComponent<Animator>();
        animation = gameObject.GetComponent<Animation>();
    }



    void Update()
    {

        // Pour Avancer

        if (Input.GetKey(inputFront))

        {
            transform.Translate(0, 0, flySpeed * Time.deltaTime);
            animation.Play("sj001_run");
            animator.SetBool("run", true);
        }
        else
        {
            animator.SetBool("run", false);
        }



        // Pour Sprinté

        if (Input.GetKey(inputFront) & Input.GetKey(inputSprint))

        {
            transform.Translate(0, 0, (flySpeed * 1.2f) * Time.deltaTime);
            animation.Play("sj001_run");
            animator.SetBool("sprint", true);
        }
        else
        {
            animator.SetBool("sprint", false);
        }



        // Pour Attaquer

        if (canAttaque = true && (Input.GetKey(inputAttaque)))
        {
            StartCoroutine(coroutAttaque());
        }
        else
        {
            animator.SetBool("attaque", false);
        }



        // Pour Reculer 

        if (Input.GetKey(inputBack))
        {
            transform.Translate(0, 0, -(flySpeed / 6) * Time.deltaTime);
            animation.Play("sj001_wait");
            animator.SetBool("back", true);
        }
        else
        {
            animator.SetBool("back", false);
        }



        // Pour Tourner à Gauche

        if (Input.GetKey(inputLeft))
        {
            transform.Rotate(0, -turnSpeed * Time.deltaTime, 0);
        }



        // Pour Tourner à Droit

        if (Input.GetKey(inputRight))
        {
            transform.Rotate(0, turnSpeed * Time.deltaTime, 0);
        }



    }

    IEnumerator coroutAttaque()
    {
        print("Début de la coroutine & Player de peut plus attaquer");
        animation.Play("sj001_skill1");
        animator.SetBool("attaque", true);
        canAttaque = false;
        yield return new WaitForSeconds(3);
        canAttaque = true;
        print("Fin de la coroutine & Player peut attaquer");

    }


}
Voici également un vidéo du résultats lors des contrôles et aminations. Sans ma coroutine. Mon problème est que lorsqu'on maintient la touche attaque enfoncer (z) l’animation de celle-ci reste gelé. Ci on appuis une fois et on attend la fin de l'animation pour ré appuyer cela ne bug pas (voir fin du vidéo).https://youtu.be/VlaunFBMidk

Cependant même avec ma coroutine qui fonctionne (on le voie au print) lorsque je reste appuyer sur ma touche celui ci reste geler tout de même. Ce la marche ci je met GetKeyDown au lieu de GetKey, cependant je ne veux pas être oublier de relâcher le bouton pour ré attaquer une deuxième foie. Je voudrais que ci j'appuie sur mon "z" (Bouton attaque) et que je le maintiens, mon animation d'attaque joue en boucle de 3 seconde sans geler. Donc même ci je reste appuyer mon animation part, ma coroutine commencer, mon animation joue pendent mon temps de 3 seconde, ensuite il repart tant que je reste appuyer.

Comme je suis débutante j'ai de la difficulter à voir ou est ce que sa bloque et pourquoi mon animation reste toujours geler. Ce que je comprend du principe de la couroutine c'est qu'elle devrais bloquer l’utilisation de la touche attaque tant que la coroutine est en marche, permettant de rester appuyer sur le bouton et que celui ci réagisse comme ci on appuyais une fois et qu'on attendrais que l'animation soie fini pour réappuyer de nouveaux.

Avatar de l’utilisateur
Max
Messages : 8771
Inscription : 30 Juil 2011 13:57
Contact :

Re: Animation qui frezz ci touche enfoncer ! (Coroutine)

Message par Max » 22 Sep 2018 17:31

Bonjour,

bon, je n'ai pas pour le moment le temps de tout lire, mais première chose que j'ai remarqué d’emblée dans ton code, c'est que tu écris ceci:

Code : Tout sélectionner

if (canAttaque = true && (Input.GetKey(inputAttaque)))
Pour rappel, si tu cherches à faire un test d'égalité, il faut employer '==' et non '='.
donc écrire

Code : Tout sélectionner

if (canAttaque == true && (Input.GetKey(inputAttaque)))
ou dans le cas dun boolean, accessoirement

Code : Tout sélectionner

if (canAttaque  && (Input.GetKey(inputAttaque)))
Image
Pas d'aide par MP, le forum est là pour ça.
En cas de doute sur les bonnes pratiques à adopter sur le forum, consulter la Charte et sa FAQ

UnicornMaster40
Messages : 17
Inscription : 16 Sep 2018 14:15

Re: Animation qui frezz ci touche enfoncer ! (Coroutine)

Message par UnicornMaster40 » 23 Sep 2018 03:17

J'ai essayer les 2 combinaisons, mais aucune ne fonction.. avec ceux-ci l'animation ne ce joue même pas :/ ! Je suis un peut décourager quelque chose qui ma l’aire asser facile a réalise mais qui ne marche pas :(

Avatar de l’utilisateur
Liven
Messages : 268
Inscription : 30 Nov 2017 01:48

Re: Animation qui frezz ci touche enfoncer ! (Coroutine)

Message par Liven » 23 Sep 2018 04:57

J'ai l'impression qu'à aucun moment tu ne déclare canAttaque (jolie FranGlais en passant, je chari mais n'ai pas de leçons à donner) comme true pour la premier attaque (l'erreur soulevée par Max t’empêchait de t'en rendre compte)

Essaye de modifier donc ta déclaration de variable comme ça :

Code : Tout sélectionner

    private bool canAttaque = true; 
Et oui des fois on se tape la tête contre les murs pour des broutilles...

Je sais pas quel éditeur tu utilise pour ton code (et comment il est configuré), mais perso sur visual studio 17 les "simples =" dans un "if" me sont souligné comme une erreur, ça évite déjà de se faire avoir par ce truc à la c**.

UnicornMaster40
Messages : 17
Inscription : 16 Sep 2018 14:15

Re: Animation qui frezz ci touche enfoncer ! (Coroutine)

Message par UnicornMaster40 » 23 Sep 2018 13:32

J'ai chercher sur comment utilisé les variables bool ,mais je n'est pas trouvé grand chose :/. J'ai changer mon script pour mon attaque avec les solutions de max, mais comme dit plus haut sa ne fonctionne pas :\. Je pensais quand utilisant:

Code : Tout sélectionner

(Input.GetKey(inputAttaque) && canAttaque == true)
Sa ferais en sorte que lorsque j’appuie sur ma touche attaque et que ma valeur bool est en true, ma coroutine pourrais partir.

Code : Tout sélectionner

IEnumerator coroutAttaque()
    {
        canAttaque = false;
        print("Début de la coroutine & Player de peut plus attaquer");
        animation.Play("sj001_skill1");
        animator.SetBool("attaque", true);
        yield return new WaitForSeconds(3);
        canAttaque = true;
        print("Fin de la coroutine & Player peut attaquer");

    }
Que ma coroutine une fois lancer, changerais ma valeur bool en false, donc même ci j’appuierais sur ma touche attaque rien ne ce passerais vue que j'ai pas deux condition. Que à la fin de ma coroutine ma valeur bool revienne à la normal (true) qui permettrais un autre attaque.

Cependant ça ne fonctionne pas. Comme tu dit j'ai l’impression que ma valeur bool ne change jamais et n'est pas tenue en compte, alors quelle est pourtant déclarer (Je crois ) dans mes variables au début de mon script. J'ai chercher des exemples sur le net de comment la déclarer et m'en servir, mais j'ai rien trouver vraiment qui a pu m'aider.

Avatar de l’utilisateur
Liven
Messages : 268
Inscription : 30 Nov 2017 01:48

Re: Animation qui frezz ci touche enfoncer ! (Coroutine)

Message par Liven » 23 Sep 2018 14:27

Une variable bool est toujours false par défaut.

Si tu veux qu'elle soit true au démarrage il faut le faire explicitement d'une façon ou d'une autre (comme je l'ai indiqué ou alors en awake ou en start ça c'est toi qui vois).
Si tu ne le fait pas, ton bool démarre en false et comme il faut qu'il soit true pour passer une première fois dans ta couroutine, il n'y passe jamais et donc reste indéfiniment en false ce qui t'empèche d'attaquer.

Tu as essayer de faire la modif que je t'ai proposé dans mon post précédent ?



Sinon attention quand même avec les couroutines car elles ont tendance à alouer de la mémoire temporaire (c'est pas le terme, mais c'est pour être plus clair) hors régulièrement le programme va vider cette mémoire et cela occasionne souvent des piques dans les performances qui peuvent donner lieu à des mini-freeze ingame.
On a malheureusement aucun contrôle sur les allocations et leur vidage (par le garbage collector, le fameux GC qui donne des cheuveux blancs à certains) il faut donc bien surveiller régulièrement le profiler pour pas que ça prenne des proportions gênantes pour le jeu.

Perso, j'ai lâcher les couroutine et je fait mes propres compteurs. C'est moins beau, moins pro, moins propre, mais au moins je n'ai plus à me soucier de ça. (Pas sûr que ce soit la solution idéale cela dit).

Autre petite chose,

Je te conseil très vivement de n'utiliser les variables publiques que si tu as besoin d'y accéder depuis d'autres scripts. Si c'est juste les afficher dans l'inspector, la bonne pratique (que certains youtubeurs néglige ce qui est dommageable pour leur viewers) est de le déclarer ainsi :

Code : Tout sélectionner

    
    [SerializeField] private float flySpeed;
Alors c'est un poil plus long, mais avec l'autocomplétion, t'as juste à taper [ser puis entrer et le tour est jouer, c'est donc pas la mort.
Et surtout cela permet de bien distinguer les variables qui sont interne au script de celles qui sont utilisées ailleurs ce qui fait gagner beaucoup de temps pour le debbogage ou le ménage car quand tu ne suivra plus de tuto et créera tes propres scripts tu va créer des variables à la pelle, certaines seront liées à des essais que tu n'aura pas retenu, du coup il faudra les supprimer pour des raisons évidente d'opti et ne pas savoir si une variable est propre au script peut devenir problématique (en plus si t'as des variables publiques dans différents scripts qui portent le même nom, je te souhaite bien du courage pour faire le tri)

UnicornMaster40
Messages : 17
Inscription : 16 Sep 2018 14:15

Re: Animation qui frezz ci touche enfoncer ! (Coroutine)

Message par UnicornMaster40 » 23 Sep 2018 15:05

D’accord , alors sans les coroutines, qu'est ce qui serai le mieux dans mon cas ?Ci j’utilise "GetKeyDown" cela fonctionne, mais je ne veut pas avoir a réappuyer chaque fois pour un attaque. Je veux Rester appuyer sur ma touche, que l’animation "attaque" ce joue, attend "X"Seconde et ce rejoue en boucle tant que je reste appuyer, mais pour linstant ca fair que buger j'ai rien trouver qui fonctionne. Cela fait bientôt 1 semaine que je suis sur ce problème -_-. Je pensais peut être simplement ajouter un compteur. Exemple dans mon Attaque:

Code : Tout sélectionner

 if (Input.GetKey(inputAttaque))
        {
            animator.SetBool("ataque", true);
Lorsque j’appuierais sur mon "inputAttaque" en plus que ma variable bool de mon animator passe en true pour jouer mon animation, j'aimerais qu'un timer parte 3sec (temps de mon animation) et que celui-ci bloque la possibilité de pouvoir rejouer l'animation temps que mon timer n'est pas fini et lorsqu'il est terminer l'animation recommencer ainsi que le timer et tout ça en boucle, tant et aussi longtemps que je reste appuyer sur mon "inputAttaque. Lorsque je relâche mon input, je veux que la boucle ce finisse, donc jouer l'animation, attendre 3sec et revenir en idel.

Quand je regarde sa comme sa ça ma l'aire asser simple comme sa , mais je ne réussie pas à le faire ou à trouver des tutos ou explications sur le net qui pourrais m'aider à réaliser ceci :( .
Liven a écrit :
23 Sep 2018 15:00
Autre petite chose (désolé pour le double post)

Je te conseil très vivement de n'utiliser les variables publiques que si tu as besoin d'y accéder depuis d'autres scripts. Si c'est juste les afficher dans l'inspector, la bonne pratique (que certains youtubeurs néglige ce qui est dommageable pour leur viewers) est de le déclarer ainsi :

Code : Tout sélectionner

    
    [SerializeField] private float flySpeed;
En fait j'aimais bien cette méthode, car éventuellement j'aimerais que dans mon menu de démarrage (qui est très très loin encore) il y est le choix des options. Donc un joueur qui veux que son inputFront soie "L" ou Bouton Gauche de la souris au lieu de "w" (par defaut) pourra le changer lui même. À moins que cela ne l’empêche pas ?

Avatar de l’utilisateur
Liven
Messages : 268
Inscription : 30 Nov 2017 01:48

Re: Animation qui frezz ci touche enfoncer ! (Coroutine)

Message par Liven » 23 Sep 2018 18:11

Pour l'attaque : reste sur le GetKey (pas le GetKeyDown) pour déclencher l'attaque.

Puis dans ton animator, dans les propriétés de la flèche qui va de l'attaque au idle (enfin ton anim par défaut) supprime la condition "attaque = false" et coche la case "Has exit time". Le seul petit incovénient est que tu ne peut pas faire de "demi attaque", l'animation doit se jouer jusqu'au bout (si t'as vraiment besoin je peux compléter sur ce point, mais pour l'instant restons simples).
Donc ça plus le == soulevé par Max, plus la déclaration intitiale à true de canAttaque comme je l'évoquais plus bas et ça devrait rouler.

Note que le temps d'attente (que tu pourrais passer en [SerializedField] d'ailleurs ;) ) que tu met dans ta couroutine doit comprendre le temps de l'animation de l'attaque + le temps de repos que tu veux derrière.


Pour les couroutine, voici ce que donnerais la même fonctionnalité avec un compteur maison basique :

Code : Tout sélectionner

    [SerializeField] private float canAttackDelay;
    private float canAttackCount;

    [SerializeField] private string inputAttaque;
    [SerializeField] private Animator animator;

    void Update ()
    {
        if (canAttackCount > 0.0f)
        {
            canAttackCount -= Time.deltaTime;
            animator.SetBool("attaque", false);
        }
        else if (Input.GetKey(inputAttaque))
        {
            animator.SetBool("attaque", true);
            canAttackCount = canAttackDelay;
        }
    }
C'est comme ça que je procède généralement. C'est pas super élégant, mais ça fait le taf sans risque lié au GC.
Après à toi de voir selon tes besoins / habitudes / préférences, et n'hésite à checker le profiler quand tu fait des couroutines pour t'assurer qu'elles ne crée pas de pic de GC.

pour être vraiment opti il faudrais ne pas executer le "animator.SetBool("attaque", false);" aussi souvent car unity va checker un string et ça fait parti des choses à minimiser quand un peut (lui coller un bool au cul par exemple) mais j'ai voulu rester clair sur le principe.

UnicornMaster40
Messages : 17
Inscription : 16 Sep 2018 14:15

Re: Animation qui frezz ci touche enfoncer ! (Coroutine)

Message par UnicornMaster40 » 23 Sep 2018 22:23

Merci :) j'aime bien cette méthode pour le timer c'est facile de comprendre le fonctionnement. L'animation ne gèle plus, par contre le timer na pas l’aire de marcher car même ci je met 10 (10sec) dans mon timer pour que sa prenne 10 seconde avant de relancer l’animation cela ne l’empêche pas de jouer ci je réappuis sur ma touche d'attaque. Je doit également réappuyer, car ci je reste appuyer , l'animation ne bug plus mais ne joue qu'un fois :o

Voila le code avec vos modification intégrer a mon script !

Code : Tout sélectionner

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class teste2 : MonoBehaviour {
   
    private Animator animator;
    private float canAttackCount;
    public float flySpeed;
    public float turnSpeed;
    [SerializeField] private float canAttackDelay;
    [SerializeField] private string inputAttaque;
    



    //Controle
    public string inputFront;
    public string inputSprint;
    public string inputBack;
    public string inputLeft;
    public string inputRight;
    public string inputCamera;



    void Start()
    {
        animator = GetComponent<Animator>();
        
    }



    void Update()
    {
        // Pour attaquer
        if (canAttackCount > 0.0f)
        {
            canAttackCount -= Time.deltaTime;
            animator.SetBool("attaque", false);
        }
        else if (Input.GetKey(inputAttaque))
        {
            animator.SetBool("attaque", true);
            canAttackCount = canAttackDelay;
        }
    
        
        // Pour Avancer

        if (Input.GetKey(inputFront))

        {
            transform.Translate(0, 0, flySpeed * Time.deltaTime);
            animator.SetBool("run", true);
        }
        else
        {
            animator.SetBool("run", false);
        }



        // Pour Sprinté

        if (Input.GetKey(inputFront) & Input.GetKey(inputSprint))

        {
            transform.Translate(0, 0, (flySpeed * 1.2f) * Time.deltaTime);
            animator.SetBool("sprint", true);
        }
        else
        {
            animator.SetBool("sprint", false);
        }


        // Pour Reculer 

        if (Input.GetKey(inputBack))
        {
            transform.Translate(0, 0, -(flySpeed / 6) * Time.deltaTime);
            animator.SetBool("back", true);
        }
        else
        {
            animator.SetBool("back", false);
        }



        // Pour Tourner à Gauche

        if (Input.GetKey(inputLeft))
        {
            transform.Rotate(0, -turnSpeed * Time.deltaTime, 0);
        }



        // Pour Tourner à Droit

        if (Input.GetKey(inputRight))
        {
            transform.Rotate(0, turnSpeed * Time.deltaTime, 0);
        }


        // Attaquer

        if (Input.GetKeyDown(inputAttaque))
        {
            animator.SetBool("attaque", true);

        }

        else
        {
            animator.SetBool("attaque", false);
        }
    }

}

Avatar de l’utilisateur
Liven
Messages : 268
Inscription : 30 Nov 2017 01:48

Re: Animation qui frezz ci touche enfoncer ! (Coroutine)

Message par Liven » 24 Sep 2018 03:36

Ha ba ouai, mais faut que tu vire ça maintenant (à la fin de ton script) :

Code : Tout sélectionner

	if (Input.GetKeyDown(inputAttaque))
        {
            animator.SetBool("attaque", true);
        }
        else
        {
            animator.SetBool("attaque", false);
        }
Puisque tout ce qui est attaque et attente est géré par le timer que je t'ai filé.

PS : essaie de ne pas trop sauter de lignes dans ton code quand tu postes ici pour faciliter la lecture car la fenêtre n'ai pas immense et ça évite de trop avoir à scroller car avoir juste un petit bout de code sous les yeux ne facilite pas sa compréhension

Répondre

Revenir vers « (C#) CSharp »