[MY - AL] Pertes de contenu de variables entre deux blocs

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
BourjijKiller
Messages : 4
Inscription : 15 Juin 2018 14:49

[MY - AL] Pertes de contenu de variables entre deux blocs

Message par BourjijKiller » 15 Juin 2018 15:09

Bonjour à tous !

J'ai découvert le logiciel Unity il y a 2 mois de cela, mais je pratique la programmation objet depuis 3 ans, et mon souçi est plutôt technique (code pur).

J'ai programmé un script permettant d'ouvrir des portes battantes (avec une rotation de l'angle). Ce script dépend d'un autre script, permettant la détection du player vers la zone de porte avec une méthode OnTriggerEnter().

Voici mon problème : J'ai deux variables, permettant de définir un angle (private int angle;) d'ouverture et de fermeture (plutôt un nombre de pas d'ouverture et de fermeture) et une autre variable permettant de récupérer l'angle à chaque frame (private int currentAngle;). Une fois que le player a passé le script DoorsDetection.cs, et qu'il rencontre le Trigger collé à la poignée de la porte, le script DoorsRotation se lance.

Tant que this.currentAngle < this.angle est vérifiée, currentAngle s'incrémente. Si cette dernière n'est plus vérifiée, alors l'ouverture passe à False et la fermeture passe à True.

Une fois qu'on sort du bloc this.Openning, mes deux variables passent à 0 sans explications, et on rentre donc dans le bloc this.Closing avec des variables dont la valeur est 0 (testé en mode debug avec des espions). :( :(
Après des heures de recherche et de test sans succès, je me réfère donc à vous.

Voici le code de mon script DoorsRotation.cs.

Merci d'avance pour votre aide !

Code : Tout sélectionner

using System.Collections;
using UnityEngine;

public class DoorsRotation : MonoBehaviour
{
    #region Declaration Variables
    [SerializeField]
    private int currentAngle;
    // Angle d'ouverture de la porte
    [SerializeField]
    private int angle;
    [SerializeField]
    private static float timer;
    [SerializeField]
    private BoxCollider triggerInfo;
    [SerializeField]
    private CapsuleCollider triggerPoignee;
    // Composants du vive
    [SerializeField]
    private SteamVR_TrackedObject trackedObj;
    // Récupère l'entrée du vive
    [SerializeField]
    private SteamVR_Controller.Device inputVive
    {
        get
        {
            return SteamVR_Controller.Input((int)this.trackedObj.index);
        }
    }

    [SerializeField]
    private DoorsDetection doorsDetection;
    #endregion

    #if UNITY_EDITOR
        #region Show Statics Variables for test
        public float staticTimer;
    #endregion
    #endif

    /// <summary>
    /// Passage de la variable <seealso cref="DoorsDetection.Openning"/> a true, permettant l'ouverture de la porte
    /// Si <seealso cref="doorsDetection.ViveConnected"/> vaut true, on vérifie que le player presse le bouton du vive (ID 14 || ID 15) avant d'ouvrir la porte
    /// </summary>
    /// <param name="collider"></param>
    private void OnTriggerEnter(Collider collider)
    {
        this.currentAngle = 0;
        // Ajustement de l'angle en fonction de certaines portes
        switch(DoorsDetection.Door.parent.name)
        {
            case "Door_Middle_Left_6":
                this.angle = 150;
                break;
            case "Door_Middle_Left_7":
            case "Door_Middle_Left_8":
                this.angle = 140;
                break;
            case "Door_Office_Left_1":
            case "Door_Office_Left_2":
            case "Door_Office_Left_3":
            case "Door_Center_1":
                this.angle = 60;
                break;
            case "Door_Middle_Left_9":
            case "Door_Middle_Left_10":
                this.angle = 130;
                break;
            default:
                this.angle = 180;
                break;
        }

        // Get DoorsDetection Data
        this.doorsDetection = DoorsDetection.Door.Find("ZoneDoorsMsg").GetComponent<DoorsDetection>();
        // Si le vive est connecté, on doit presser le bouton Trigger du vive pour ouvrir la porte
        if (this.doorsDetection.ViveConnected)
        {
            this.trackedObj = GetComponent<SteamVR_TrackedObject>();
            if(this.inputVive.GetPressDown(SteamVR_Controller.ButtonMask.Trigger))
            {
                DoorsDetection.Openning = true;
                timer = 20;
                this.triggerInfo = DoorsDetection.Door.Find("ZoneDoorsMsg").GetComponent<BoxCollider>();
                this.triggerPoignee = DoorsDetection.Door.Find("TriggerDoors").GetComponent<CapsuleCollider>();
                StartCoroutine(this.disabledTriggerForTime());
                this.triggerPoignee.isTrigger = false;
            }
        }
        else
        {
            DoorsDetection.Openning = true;
            timer = 20;
            this.triggerInfo = DoorsDetection.Door.Find("ZoneDoorsMsg").GetComponent<BoxCollider>();
            this.triggerPoignee = DoorsDetection.Door.Find("TriggerDoors").GetComponent<CapsuleCollider>();
            StartCoroutine(this.disabledTriggerForTime());
            this.triggerPoignee.isTrigger = false;
        }
    }

    /// <summary>
    /// Permet de lancer la méthode <see cref="OpenDoor(bool)"/> et <see cref="CloseDoor(bool)"/>, respectivement en fonction de la valeur des variables <see cref="DoorsDetection.Openning"/>
    /// && <see cref="DoorsDetection.Closing"/>
    /// </summary>
    private void FixedUpdate()
    {
        #if UNITY_EDITOR
            // Show variables statics for test
            this.staticTimer = timer;
        #endif

        if (DoorsDetection.Openning)
        {
            if (this.currentAngle < this.angle)
            {
                this.currentAngle += 1;
                this.OpenDoor(DoorsDetection.CoteAngle);
            }

            else
            {
                Debug.Log(timer);
                timer -= Time.deltaTime;
                if(timer <= 0)
                {
                    DoorsDetection.Openning = false;
                    DoorsDetection.Closing = true;
                }
            }
        }

        // MES VARIABLES REPASSENT A 0 

        if(DoorsDetection.Closing)
        {
            Debug.Log(this.currentAngle);
            Debug.Log(this.angle);
            Debug.Log("jhdjkfdhszkjfhdskj");
            if (this.currentAngle > 0)
            {
                this.currentAngle -= 1;
                this.CloseDoor(DoorsDetection.CoteAngle);
            }

            else
            {
                DoorsDetection.Closing = false;
                DoorsDetection.Door.rotation = DoorsDetection.RotationBase;
                this.triggerPoignee = DoorsDetection.Door.Find("TriggerDoors").GetComponent<CapsuleCollider>();
                this.triggerPoignee.isTrigger = true;
                this.doorsDetection = null;
            }
        }
    }

    /// <summary>
    /// Ouverture de la porte, avec détermination du côté d'ouverture avec le paramètre <paramref name="cote"/>
    /// </summary>
    /// <param name="cote"></param>
    private void OpenDoor(bool cote)
    {
        DoorsDetection.Door.transform.RotateAround(DoorsDetection.Pivot.position, cote ? Vector3.down : Vector3.up, this.currentAngle * Time.deltaTime * 1.5F);
    }

    /// <summary>
    /// Fermeture de la porte, avec détermination du côté d'ouverture avec le paramètre <paramref name="cote"/>
    /// </summary>
    /// <param name="cote"></param>
    private void CloseDoor(bool cote)
    {
        DoorsDetection.Door.transform.RotateAround(DoorsDetection.Pivot.position, cote ? Vector3.up : Vector3.down, this.currentAngle * Time.deltaTime * 1.5F);
    }

    /// <summary>
    /// Coroutine permettant de désactiver le Trigger de détection pendant 5 secondes
    /// </summary>
    /// <returns></returns>
    private IEnumerator disabledTriggerForTime()
    {
        Debug.Log("Déclenchement de la coroutine pour désactiver le trigger" + this.triggerInfo.name + " message");
        this.triggerInfo.enabled = false;
        this.triggerInfo.isTrigger = false;
        yield return new WaitForSeconds(5F);
        this.triggerInfo.enabled = true;
        this.triggerInfo.isTrigger = true;
        yield return 0;
    }
}

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

Re: [MY - AL] Pertes de contenu de variables entre deux blocs

Message par boubouk50 » 15 Juin 2018 15:36

Est-ce que le OnTriggerEnter () est appelé plusieurs fois? Cela réinitialiserait currentAngle.
Par contre, la possibilité que this.angle = 0 n'a pas l'air d'exister, et ça c'est bizarre.

Après, pour la conception de ton code, tout est figé, c'est pas très friendly. Mieux vaudrait une classe Porte qui contient les données de base utilses, et une classe qui ne gère que les rotations. Là, tout est écrit en dur, c'est pas du tout POO.
"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

BourjijKiller
Messages : 4
Inscription : 15 Juin 2018 14:49

Re: [MY - AL] Pertes de contenu de variables entre deux blocs

Message par BourjijKiller » 15 Juin 2018 16:08

Bonjour,

Merci de votre réponse.

Au début, je n'avais pas rajouté l'instruction this.currentAngle = 0;, je l'ai fais au cas où... Mais dans tout les cas, la fonction OnTriggerEnter n'est pas ré-exécutée puisque le Trigger est désactivé jusqu'à la fermeture de la porte (la variable this.triggerPoignee contient le trigger poignée, dont le script est attaché).

Pour ce qui concerne le code, je comprends bien votre remarque, mais si on ne met rien en dur, comment récupérer les gameObjects ? Parce qu'en soit, les seules choses en dur sont les pas pour les angles et les GameObjects ^^.

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

Re: [MY - AL] Pertes de contenu de variables entre deux blocs

Message par boubouk50 » 15 Juin 2018 16:40

Le gameObject est généralement lié au Trigger.
Dans l'idée, tu peux avoir un parent Gond pour la rotation, un trigger pour l'espace d'action, un trigger pour la poignée, et un Mesh pour la porte.
>Trigger spatialisé
>Gond (utilisé pour la rotation uniquement)
>> Porte (Mesh)
>>> Poignée (Mesh)
>>> Trigger poignée

Dans tous les cas de porte, tu pourrais retrouver la même hiérarchie. Le trigger spatialisé permet de déclencher l'event "Entrer dans la zone d'action de la porte" (par exemple pour afficher un UI ou autre).
Le trigger poignée lui déclencherait l'event "ouverture" ou "fermeture" de la porte. Le Gond est la parent du parent ou bien le premier parent possédant le script de ouverture/fermeture. (GetComponentInParent () Facile à trouver donc) et déclencherai l'animation d'ouverture/fermeture (facile vitesse 1 ou -1 de la même animation) ou bien un rotation prédéfinie par deux angles (pareil un simple booléen pour l'état et un entier 1 ou -1 pour le sens).
"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

BourjijKiller
Messages : 4
Inscription : 15 Juin 2018 14:49

Re: [MY - AL] Pertes de contenu de variables entre deux blocs

Message par BourjijKiller » 15 Juin 2018 17:00

D'accord, cela se rapproche de ce que j'ai imaginé (avec un pivot, etc...), mais c'est vrai que je pensais que setter les variables directement dans le code était plus propre :gene:

Ceci étant dit, je n'ai pas trop le temps de refaire tout mon script, et j'aimerai vraiment comprendre pourquoi mes variables repassent à la valeur initiale comme par magie... :-D

Moi 1971
Messages : 727
Inscription : 29 Sep 2015 13:38

Re: [MY - AL] Pertes de contenu de variables entre deux blocs

Message par Moi 1971 » 16 Juin 2018 10:00

Bonjour,
Tu peux essayer de mettre plus de Debug.log("") dans le OnTriggerEnter.
Pour ton problème, je pencherais pour du code séquentiel et du code événementiel qui se font concurrence.
Avec un Debug, il faut compter le nombre de fois où le code rentre dans OnTriggerEnter (logiquement une seule fois?!?) et combien de fois tu passes dans le FixedUpdate dans le même temps. En plus, pour simplifier, tu utilises disabledTriggerForTime en même temps...
Peut-être le problème vient de là.

BourjijKiller
Messages : 4
Inscription : 15 Juin 2018 14:49

Re: [MY - AL] Pertes de contenu de variables entre deux blocs

Message par BourjijKiller » 18 Juin 2018 09:41

Bonjour,

Merci pour ta réponse ! En effet, on ne passe qu'une seule fois dans la méthode OnTriggerEnter (lorsqu'on s'approche suffisamment près de la porte en réalité).
Après un gros casse-tête ce week-end, je me suis posé une question. Si vraiment la variable change, cela veut signifier qu'à un moment donné dans mon code, je lui assigne la valeur 0 mais je ne trouve pas où...
Donc, j'ai mis la variable en constante :lol: :lol: et normalement, Unity aurait du me sortir une erreur ! Et bah non :pleur4:

Mais cependant, en constante, la variable n'a pas changée de valeur et ne s'est pas mise à 0...
Et puis, encore plus surprenant, la variable this.currentAngle ne change pas non plus !
Les mystères de l'informatique...

Du coup, j'ai fais une classe, composée seulement de constantes et je les utilises dans mon script de rotation, et cela fonctionne parfaitement ! Mais pourquoi ?!!!! :| :idea:

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

Re: [MY - AL] Pertes de contenu de variables entre deux blocs

Message par boubouk50 » 18 Juin 2018 10:16

Une variable entière non initialisée prend par défaut la valeur 0.
Peut-être ne passes-tu pas dans le switch pour initialiser angle.

Pour moi, il faut quand même revoir ton système. C'est vraiment pas pratique et peu soumis à extension. Et à chaque nouvelle porte, tu devras l'ajouter à ton code. Aucune modularité donc, ça pourrait entrainer des problèmes futurs.
"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

Répondre

Revenir vers « (C#) CSharp »