[Résolu] Ca marche ! Ah non.. ( Rotation Quaternion )

Questions à propos du scripting. Hors Shader, GUI, Audio et Mobile.
Avatar de l’utilisateur
NodaMegumi
Messages : 11
Inscription : 02 Août 2019 00:30
Localisation : Lyon

[Résolu] Ca marche ! Ah non.. ( Rotation Quaternion )

Message par NodaMegumi » 02 Août 2019 12:36

Bonjour, je suis débutante en C# j'ai un problème dans un script que je n'arrive pas a résoudre.

J'ai fait un script rattaché à chaque entité (slim) qui va lire les actions qu'il doit faire, et un autre non MonoBehaviour où sont répertoriés les actions (je sais pas si c'est comme ça qu'il faut faire mais bon j'essaye :hehe: ).

Aucun problème pour l'action de destination aléatoire, mais pour la rotation aléatoire il y a un problème.
Aucun message d'erreur, ils font les rotations correctement mais au bout d'un moment ils se bloquent et n'arrive plus à atteindre la rotation voulue.. Du coup l'action est toujours en cours. Ce n'est jamais au même moment, et avec des rotations différentes. J'ai déjà testé de changer les degrés aléatoire de la rotation, le Slerp en Lerp etc... mais sans succès car je ne sais même pas a quel moment ca merde. :triste1:
Le fait que le problème survienne qu'après avoir laissé tourner le jeu un moment me perturbe et je bloque depuis un moment là dessus... Si quelqu'un a une idée j'en serai ravie!

Script sur le slim ( MonoBehaviour )

Code : Tout sélectionner

    void ActionsMaker()
    {
        //S'il a des actions a faire et qu'aucune n'est en cours
        if (actions.Count > 0 && currentAction == false)
        {
            //S'il doit faire une action aléatoire, choisit aléatoirement un angle
            if(actions[0] == "randomRotate")
            {
                randomDegrees = Random.Range(10,91);
            }
            //Action en cours
            currentAction = true;
        }
    }    //Appelé dans la fonction Update()

Code : Tout sélectionner

    void UpdateCurrentAction()
    {
        //Si une action est en cours
        if (currentAction == true)
        {          
            //Met a jour les actions 
            SlimActions.UpdateActions(transform, actions[0]);
        }
    }    //Appelé dans la fonction Update()
Script Actions ( Non MonoBehaviour )

Code : Tout sélectionner

public static void UpdateActions(Transform slim, string action)
    {
        //Definitions
        SlimMotor slimMotor = slim.GetComponent<SlimMotor>();

        if(action == "randomRotate")
        {
            Debug.Log("rotating...");

            //Rotation
            Quaternion randomRotation = Quaternion.Euler(slim.rotation.x, slimMotor.randomDegrees, slim.rotation.z);
            slim.rotation = Quaternion.Slerp(slim.rotation, randomRotation, 2 * Time.deltaTime);

            //Si la rotation est terminée
            if (slim.rotation == randomRotation)
            {
                //Supprime l'action
                slimMotor.actions.Remove(action);
                //Plus d'action en cours
                slimMotor.currentAction = false; 
            }
        }
        }
Merci d'avance à ceux qui prendront le temps de me lire et peut être de me répondre! :)
Dernière édition par NodaMegumi le 02 Août 2019 15:17, édité 1 fois.

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

Re: Ca marche ! Ah non.. ( Rotation Quaternion )

Message par Max » 02 Août 2019 13:49

Bonjour, et bienvenue.

Sans vraiment entrer dans la logique de ton code, je dirais d’instinct que le point faible se situe ici:

Code : Tout sélectionner

            //Si la rotation est terminée
            if (slim.rotation == randomRotation)
Ce genre de test est toujours délicat sur les quaternions.
La doc précise bien ceci:
This function tests whether dot product of two quaternions is close to 1.0.

Note that because quaternions can represent rotations that are up to two full revolutions (720 degrees), this comparison can return false even if resulting rotations look the same.
Peut-être donc la piste à suivre.
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

Avatar de l’utilisateur
NodaMegumi
Messages : 11
Inscription : 02 Août 2019 00:30
Localisation : Lyon

Re: Ca marche ! Ah non.. ( Rotation Quaternion )

Message par NodaMegumi » 02 Août 2019 14:59

Je me disais bien que le problème venait de ma condition de fin d'action, mais je comprenais pas pourquoi ca marchait mais pas tout le temps, maintenant je comprends mieux ! Merci Max, maintenant je vais essayer de trouver une autre manière de détecter la fin de la rotation.

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6186
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: [Résolu] Ca marche ! Ah non.. ( Rotation Quaternion )

Message par boubouk50 » 02 Août 2019 15:43

Je pense qu'il faut que tu revoies ton interpolation linéaire.

Code : Tout sélectionner

slim.rotation = Quaternion.Slerp(slim.rotation, randomRotation, 2 * Time.deltaTime);
Ce que tu fais c'est tendre exponentiellement vers la valeur randomRotation sans jamais l'atteindre, puisque ta rotation originelle se rapproche petit à petit. C'est une utilisation non conventionnelle du Lerp qui te fait croire que tu l'utilises correctement.
Les deux rotations, départ et arrivée, ne devraient pas varier et l'interpolant, quant à lui, devrait aller de 0 vers 1 (dans ton cas). Ainsi, la fin de la rotation revient à vérifier l'interpolant et pas la rotation.
Qui plus est, je ne comprends pas l'utilisation de randomRotation. Il varie à chaque Update?
Si oui, alors tendre vers une rotation sera impossible puisque l'arrivée changera à chaque fois.
Si non, alors tu la redéfinis pour rien.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

Avatar de l’utilisateur
NodaMegumi
Messages : 11
Inscription : 02 Août 2019 00:30
Localisation : Lyon

Re: [Résolu] Ca marche ! Ah non.. ( Rotation Quaternion )

Message par NodaMegumi » 02 Août 2019 16:00

Merci de ta réponse boubouk50.
En effet, je débute et j'ai utilisé le Lerp sans trop comprendre en quoi il consiste réellement, pour faire une rotation "smooth", solution que j'ai trouvé sur un forum et qui avait l'air de marcher. :gene:

En cherchant comment comparer les Quaternions, je suis tombée sur cette ligne :

Code : Tout sélectionner

if (Quaternion.Angle(slim.rotation, randomRotation) < 1)
qui a l'air de marcher.

Ils suggèrent également d'utiliser plutôt un RotateTowards que Lerp, je vais donc me renseigner sur le sujet.

Et pour la randomRotation, non un degrée aléatoire est défini (une seule fois) juste avant que l'action ne commence, plus tôt dans le script propre a chaque entité, sinon ils font tous la même rotation.

Code : Tout sélectionner

     if (actions.Count > 0 && currentAction == false)
        {
            //S'il doit faire une rotation aléatoire, choisit aléatoirement un angle
            if(actions[0] == "randomRotate")
            {
                randomDegrees = Random.Range(-180,180);
            }
            //Action en cours
            currentAction = true;

Répondre

Revenir vers « Scripting »