Faire tomber un objet puis le faire remonter Unity

Fermé
ProjektSpark Messages postés 3 Date d'inscription mercredi 6 juin 2018 Statut Membre Dernière intervention 8 juin 2018 - Modifié le 7 juin 2018 à 09:25
 ProjektSpark - 11 juin 2018 à 18:09
Bonjour,
depuis quelques jours j'essaye tant bien que mal de terminer un code me permettant de faire tomber un objet au passage du joueur puis de le faire remonter (comme les fameux stompers de mario par exemple). J'ai donc mis un circlecast en update, et une variable boolean qui détermine si l'objet peut engager son mouvement, pour ne pas que la coroutine se lance plusieurs fois.


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

public class FallingObject : MonoBehaviour
{
    //temps d'attente
    public float AttenteHaut = 1;
    public float AttenteBas = 1;
    public float Réinitialisation;
    //vitesse
    public float SpeedAller;
    public float SpeedRetour;
    
    public Transform Position;
    public Transform Target;
    public Transform Player;
    public float OffsetX = 0;
    public float OffsetY = 0;
    public float End = 5;
    public float Radius = 2;
    public bool AttackMode;

    private void Start()
    {
        AttackMode = false;
    }

    IEnumerator HammerFall()
    {
        AttackMode = true;
        Vector2 target = new Vector2(Target.position.x, Target.position.y);
        Vector2 position = new Vector2(Position.position.x, Position.position.y);
        Vector3 Aller = Vector3.MoveTowards(transform.position, target, SpeedAller * Time.deltaTime);
        Vector3 Retour = Vector3.MoveTowards(transform.position, position, SpeedRetour * Time.deltaTime);
        yield return new WaitForSeconds(AttenteHaut);
        gameObject.GetComponent<Rigidbody2D>().MovePosition(Aller);
        if (Vector2.Distance(transform.position, Target.position) <= 0.1)
        {
            Debug.Log("Aller Terminé");
            yield return new WaitForSeconds(AttenteBas);
            gameObject.GetComponent<Rigidbody2D>().MovePosition(Retour);
            if (Vector2.Distance(transform.position, Position.position) <= 0.1)
            {
                Debug.Log("Terminé");
                yield return new WaitForSeconds(Réinitialisation);
                AttackMode = false;
                StopCoroutine(HammerFall());
            }
        }
    }


    void Update()
    {
        {
            Vector2 target = new Vector2(Target.position.x + OffsetX, Target.position.y + OffsetY);
            RaycastHit2D hit = Physics2D.CircleCast(transform.position, Radius, target, End);
            Debug.DrawRay(transform.position, target, Color.green);
            if (hit.collider != null)
            {
                if (hit.collider.gameObject.transform == Player & AttackMode == false)
                {
                    StartCoroutine(HammerFall());
                }
            }
        }
    }
}



Grace aux différents Debug.log, j'ai situé les problèmes: d'abord, malgré son déplacement, l'objet, quand il a atteint sa cible, ne trigger pas la fin de son mouvement, et n'entame donc pas le second (la remontée): je ne reçois donc pas de "Aller Terminé". Pourtant, l'objet et la cible se retrouvent à la même position (axe Z compris, c'est un jeu en 2D)...
Deuxièmement, l'objet ne se déplace pas vers sa destination mais s'y téléporte instantanément, même avec une vitesse très basse. Les variables "Speed" changent toutefois la distance à laquelle l'objet se téléporte (et à laquelle il reste d'ailleurs).


Si quelqu'un pouvait m'aider ça me sauverait bien svp, merci d'avance !



4 réponses

ProjektSpark Messages postés 3 Date d'inscription mercredi 6 juin 2018 Statut Membre Dernière intervention 8 juin 2018
7 juin 2018 à 15:50
Je up parce que j'ai toujours pas trouvé et que j'aimerai bien finir mon code (dont cette partie est la dernière)
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 928
7 juin 2018 à 20:29
Bonjour,

tout d'abord, merci à Francis, d'avoir corriger la coloration de ton code.
En effet, tu n'avais pas précisé le langage et cela donnait un pavé tout gris, sans numéro de ligne et pas scroll able.
Voir ici, pour mieux utiliser la coloration syntaxique https://codes-sources.commentcamarche.net/faq/10686-le-nouveau-codes-sources-comment-ca-marche#balises-code

Je ne connais pas Unity, mais C# oui, voici quelques remarques générales.

Les champs publiques c'est contraire au principe d'encapsulage, base de la programmation objet.
C'est "dangereux" car tout le monde peut accéder aux variables internes de l'objet.
Les deux bonnes façons de faire sont:
  • utiliser des getter et des setter
    private bool AttackMode;
    
    public void SetAttackMode(bool Valeur)
    {
        AttackMode = Valeur;
    }
    
    public bool GetAttackMode()
    {
        Return AttackMode;
    }
    
  • utiliser des propriétés
            private bool attackMode;
    
            public bool AttackMode
            {
                get { return attackMode; }
                set { attackMode = value; }
            }


Les propriétés ont plusieurs avantages
  • tu peux les mettre en lecture seule, en écriture seule ou en accès complet
  • le binding fonctionne uniquement avec les propriétés
  • pour implémenter INotifyPropertyChanged, il faut des propriétés
  • tu peux créer des propriétés qui retournent un résultat, par exemple la propriété Age en lecture seule est la différence entre aujourd'hui et la date de naissance.
  • si tu n'a pas besoin d'une variable interne, tu peux écrire une propriété simplifiée (ce qui n'empêche pas de revenir à la version normale par la suite)
    public bool AttackMode { get; set; }
  • tu peux les écrire rapidement grâce aux snippets "prop" et "propfull"


C# est un langage qui compile en 32 ou 64 bits, ce qui veut dire que la mémoire est "découpée" en blocs de 32 bits. Utiliser des variables 16 bits (comme le float) revient à remplir la moitié du bloc de 32bits (le 1/4 pour un bloc de 64) et laisser le reste vide.
En plus tu perds en précision et "étendue de mesure". Imaginons un nombre affiché en notation scientifique, 4 caractères pour les nombres et la virgule (la mantisse) et 1 caractère pour l'exposant:
  • le maximun possible est 9999 E9
  • tout nombre entre 1.23 et 1.24 E3 n'existe pas.

Maintenant, si on double la capacité de la mantisse et de l'exposant
  • le maximum possible est 99999999 E99
  • les nombres entre 1.234567 et 1.234568 E03 n'existent pas

Pour les float et les doubles c'est la même idée, sauf que la mantisse et l'exposant sont en puissance de 2. Pour plus d'info https://fr.wikipedia.org/wiki/Virgule_flottante
Les 2 seuls moments où il est nécessaire d'utiliser des float, des int16, ou n'importe quelle type en 16 bits, sont
  • travailler avec une dll compilée en 16 bits dont il n'existe aucun équivalent récent (c'est rare)
  • écrire un fichier propriétaire ou des données sont définies en 16bits.


Enfin, pour débugger, le plus simple n'est pas de se servir des logs (ça c'est plus pour comprendre des phénomènes qui apparaissent en realease et pas en debug). Il est bien plus efficace de mettre un point d'arrêt à une ligne de code judicieuse, puis d'exécuter en pas à pas, d'observer les contenus des différentes variables (avec les espions par exemple) et le comportement du fil en fonction de ces contenus.

0
ProjektSpark Messages postés 3 Date d'inscription mercredi 6 juin 2018 Statut Membre Dernière intervention 8 juin 2018
8 juin 2018 à 14:18
Déjà merci pour le temps que tu as passé sur ce message, et désolé si j'ai mal présenté mon code et mon problème.
Je suis un débutant sur Unity et C# donc j'ai du mal avec beaucoup de choses, du coup merci pour ta réponse qui m'aidera sans doute à mieux comprendre la programmation !
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 928
8 juin 2018 à 19:46
Il est peut-être judicieux d'apprendre les bases du C#, et ensuite reprendre ton projet Unity.
Ce cours https://tahe.developpez.com/dotnet/csharp/ est bien, ça te prendra quelques jours.

Pour débugguer ton problème, vu ta description, je pense qu'il faut mettre le point d'arrêt à cette ligne
        if (Vector2.Distance(transform.position, Target.position) <= 0.1)

Mettre un espion sur transform.position, Target.position et Vector2.Distance(transform.position, Target.position) pour voir si le calcul est cohérent et si la distance diminue à chaque avancée.
Si le calcul n'est pas cohérent, c'est que le problème se situe dans la méthode Distance.
Si la position ne bouge pas, alors il y a un problème d'attribution
Etc...
0
Whismeril Messages postés 19025 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 19 avril 2024 928
8 juin 2018 à 20:07
Ici un tuto pour bien utiliser le debugger dans Visual Studio
https://openclassrooms.com/fr/courses/1526901-apprenez-a-developper-en-c/2867766-utilisez-le-debogueur

Et ici pour Unity
https://upln.fr/utiliser-le-mode-debug-de-linspector-dans-unity/ en général, je ne suis pas fan des tutos vidéo pour la programmation, mais celui-là m'a l'air pas mail et il ne traite pas directement de vidéo.
0
ProjektSpark
11 juin 2018 à 18:09
Merci beaucoup pour tout, je vais regarder cela
0