[Résolu][DB-AL] Rebond calculé et précis d'un objet

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
Avatar de l’utilisateur
Spiriusis
Messages : 6
Inscription : 26 Oct 2018 15:30

[Résolu][DB-AL] Rebond calculé et précis d'un objet

Message par Spiriusis » 26 Oct 2018 15:59

Bonjour !

Depuis quelques temps je m'essaye à Unity en réalisant un clone d'un jeu mobile pour Android uniquement de type "Splashy" (cf le Playstore) . Dans ma réplique je fais différemment, au lieu de devoir déplacer horizontalement une balle qui arrive vers des plateformes pour permettre son rebond, ce sont les plateformes qui arrivent vers la balle qui reste fixe (effectue seulement un rebond vertical quand une plateforme arrive). Comme je code un petit peu en mode "blaireau" en tâtonnant un peu ^^, je remarque que mes script ne me permettent pas d'arriver là où je veux, c'est à dire faire en sorte que même au bout du nème rebond, la balle atterrit toujours au milieu de la plateforme (et quelque soit la vitesse, la distance entre celles-ci ...) Je suis à peu près bon dans le calcul mais un léger décalage subsiste, qui ne semble pas venir d'une double activation et cause toujours un micro décalage qui finis inlassablement par faire tomber la balle trop en avant.

Voici mon script qui génère les plateformes (riverMin/Max sera activé plus tard pour que les plateformes soit crées un peu aléatoirement sur l'axe horizontal mais pour tester plus facilement le jeu je le laisse désactiver pour l'instant)

Code : Tout sélectionner

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

public class PlateformGenerator : MonoBehaviour {

    public GameObject thePlateform;
    public Transform generationPoint;
    private float distanceBetween = 2.8f;
    private float xPos = 45f;
    public static float centerPlateformDist;

    private float plateformWidth;

	private float riverMin = 43.5f;
	private float riverMax = 46.5f;

    public GameObject plateformClone;
    private int nextNameNumber = 1;


    void Start () {
		plateformWidth = thePlateform.GetComponent<BoxCollider>().size.x;
	}
	
	void FixedUpdate () {

        
            if (transform.position.z < generationPoint.position.z)
            {
                
                //xPos = Random.Range (riverMin, riverMax);
                transform.position = new Vector3(xPos, transform.position.y, transform.position.z + plateformWidth + distanceBetween);
                plateformClone = Instantiate(thePlateform, transform.position, transform.rotation);
                centerPlateformDist = plateformWidth + distanceBetween;
                plateformClone.name = "newPlateform" + nextNameNumber;
                plateformClone.tag = "Plateforms";
                nextNameNumber++;
            }
       
		
	}
}

Celui qui les fait se déplacer vers la balle

Code : Tout sélectionner

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

public class PlateformMove : MonoBehaviour {

    public static float plateformSpeed = 6;
    private bool freeze = false;

	void Start () {
		
	}
	
	void Update () {

        freeze = Respawning.freeze;
        if (freeze == false)
        {
            transform.Translate(-Vector3.forward * Time.deltaTime * plateformSpeed);
        }		
		
	}
}

Et enfin celui qui fait rebondir la balle (je ne sais d'ailleurs pas trop comment m'y prendre avec "l'activation" du rebond. J'utilise pour le moment un compteur qui s'active quand il y a collision et lorsque la vitesse de la balle est quasi nulle. Il ne semble pas il y avoir de double activation.)

Code : Tout sélectionner

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


public class autoJump1 : MonoBehaviour
{
    public Vector3 jump;
    Rigidbody rb;
    private float vel;

    public float v;
    private float jumpForce;
    private float T;
    private float d;
    public static int ctN = 0;
    public static int ctO = 0;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
        jump = new Vector3(0.0f, 1.0f, 0.0f);
    }

    void OnCollisionEnter()
    {
        ctN++;
    }

    void OnCollisionExit()
    {
        ctO++;
    }


    void FixedUpdate()
    {

        if (ctN > ctO && Respawning.freeze == false)
        {
      
            vel = rb.velocity.y;
            if (vel <= 0.05)

            {
                d = PlateformGenerator.centerPlateformDist;
                v = PlateformMove.plateformSpeed;
                T = d / v;

                jumpForce = (9.81f * T / 2f);
                rb.AddForce(jump * jumpForce, ForceMode.VelocityChange);
                 Vibration.Vibrate(50);
                GameManagement.Scoring();
            }
        }

    }
}

Il calcule toujours la même accélération et le décalage est léger, je ne vois pas ce qui pourrait poser soucis. A votre avis de quel paramètre cela pourrait venir ? Merci de votre aide ! :)
Dernière édition par Spiriusis le 04 Nov 2018 12:53, édité 2 fois.

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

Re: [DB-AL] Rebond calculé et précis d'un objet

Message par Liven » 26 Oct 2018 18:34

J'ai pas regarder en détail-détail, mais je me demande si ton script de génération de platforme n'aurait pas mieux ça place en update plutôt que fixeupdate (en ajoutant les delta time qui vont bien) vu qu'il n'utilise pas de physic.

Puis tu gère le mouvement de ta balle par la physics ce qui est compliqué pour avoir un mouvement maîtrisé et précis car les calculs internes de la physics sont par nature des approximations. Du coup je suis pas surpris qu'on bout d'un moment ça ce barre en cacahouète.
Je serais toi je partirais plutôt sur des mouvement contrôlé par le transfom (codé dans update donc).
Et pour déterminer si la boule est sur la platforme, faire un petit contrôle de distance (à la place des oncolliders) par rapport au centre de la platforme lorsque la boule atteins la hauteur de rebond potentiel.

Sinon dernière chose, je vois que tu as tendance à appeler plusieurs fois le même transform.position dans le même script. I faut savoir que c'est une opération gourmande (comme tous les acces en lecture ou écriture aux transforms)et qu'il est très conseillé de ne l’appeler qu'une seule fois en début de script et de stocker la position en cours dans un vecteur3 que l'on pourra checker lorsque l'on a besoin de celle-ci.
Ce conseil est valable sur toutes les platformes et d'autant plus sur mobile.

Avatar de l’utilisateur
Spiriusis
Messages : 6
Inscription : 26 Oct 2018 15:30

Re: [DB-AL] Rebond calculé et précis d'un objet

Message par Spiriusis » 28 Oct 2018 12:17

Bonjour,

Merci pour ces conseil, pour ce qui est de l'optimisation je vais régler ça après, mais pour le mouvement, même si je fais un script du genre

Code : Tout sélectionner

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

public class autoJump2 : MonoBehaviour {

    private float d;
    private float v;
    public float objectSpeed;
    private float time;

    private bool Up;

 
    void GoDown()
    {
        Up = false;
    }

    void Update()
    {
        d = PlateformGenerator.centerPlateformDist;
        v = PlateformMove.plateformSpeed;

        time = (d / v)/2;

        if (transform.position.y < 0.8)
        {
            Up = true;
            Invoke("GoDown", time);
        }

        if (Up == true)
        {
            transform.Translate(Vector3.up * Time.deltaTime * objectSpeed);
        }

        else
        {
            transform.Translate(-Vector3.up * Time.deltaTime * objectSpeed);
        }
    
    }

}
(avec y=0.8 quand la balle est sur la plateforme)
Je vois effectivement qu'on est pas loin. Le rebond se fait au bon endroit comme il faut mais toujours au bout de genre 30/40 rebond on avance beaucoup trop devant (à peu près 0.6 unités/40rebonds) . Quelque chose met-il trop de temps à s'executer ?

Cela ne semble pas venir d'un décalage de plateformes qui se situent toujours à la même distance les unes des autres. Cependant dans le script qui génère les plateformes en enlevant le FixeUpdate() j'ai un défaut de distance à la 3ème plateformes qui a du retard sur les autres (comment dois-je donc procéder pour paramétrer mon Update() et éviter cette erreur ? )

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

Re: [DB-AL] Rebond calculé et précis d'un objet

Message par Liven » 28 Oct 2018 14:36

Essais de modifier ça dans l'update de ton autojump2 :

Code : Tout sélectionner

v = PlateformMove.plateformSpeed * Time.deltaTime;
Et n'oublie pas de modifier la valeur de ta variable plateformSpeed en conséquent (normalement en la multipliant pas 50 tu devrait retomber sur tes pattes)

Avatar de l’utilisateur
Spiriusis
Messages : 6
Inscription : 26 Oct 2018 15:30

Re: [DB-AL] Rebond calculé et précis d'un objet

Message par Spiriusis » 29 Oct 2018 14:40

Euh je ne vois pas trop. C'est à dire que si je modifier mon plateformSpeed j'ai juste des plateformes qui vont beaucoup trop vite. En fait je vois bien l'utilisation du Time.deltaTime pour un déplacement régulier en lui même. Mais là c'est pour déterminer le moment où la balle est au "milieu" de la parabole (bon sauf que là ce sont les plateformes qui se déplacent mais ça revient au même). Donc je ne vois pas ce que je dois modifier exactement ? Pour le moment ça ne semble pas fonctionner.

Mis à part ça je ne me suis peut-être pas exprimé super clairement. Mais mon script utilisant les fonctions de physiques fonctionnait parfaitement à un moment. Alors je ne sais pas comment le script s'est cassé (j'ai peut-être perdu des paramètres lors de màj d'Unity ou autre, mais j'ai pourtant tout vérifier). Je suis arrivé à plus de 1000 rebonds. Là le décalage se produit rapidement et la balle tombe au bout de 30 plateformes à peine !. Il y a forcément un soucis autre part, en dehors des performances et du framerate. Je me demandais si ce n'était pas justement dû à autre chose (c'est pour cela que j'ai mis les 3 scripts qui interviennent là dedans). Mais si c'est plus pertinent, oui continuons avec le transform.translate

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

Re: [DB-AL] Rebond calculé et précis d'un objet

Message par Liven » 29 Oct 2018 15:08

Spiriusis a écrit :
29 Oct 2018 14:40
si je modifier mon plateformSpeed j'ai juste des plateformes qui vont beaucoup trop vite.
As tu adapté la valeur par défaut de ton plateformSpeed comme indiqué.

Si j'ai bien compris, tu détermines le moment ou ta balle va retomber en te basant sur son temps de monté (au bout de x temps de montée on commence la descente).

Hors à partir du moment ou tu as des calculs qui font intervenir la mesure d'un temps, tu dois passer par un deltatime si tu est en update (pour compenser les variations de framerate).

Avatar de l’utilisateur
Spiriusis
Messages : 6
Inscription : 26 Oct 2018 15:30

Re: [DB-AL] Rebond calculé et précis d'un objet

Message par Spiriusis » 29 Oct 2018 23:16

Oui c'est bien ça !

Mais là, que je fasse

Code : Tout sélectionner

v = (PlateformMove.plateformSpeed * 50) * Time.deltaTime;
Ou que je modifie la valeur d'origine dans PlateformMove

Code : Tout sélectionner

public static float plateformSpeed = 6;
soit en la multipliant par 50 directement soit dans le code lui même après, je n'ai pas l'effet escompté (ni avec d'autre valeurs).

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

Re: [DB-AL] Rebond calculé et précis d'un objet

Message par Liven » 29 Oct 2018 23:56

Et tu ne peux pas regarder ce qui a changer entre la version qui marchait et l'autre?
Là je suis à cours d'idée, une petite vidéo aiderait peut être à visualiser la chose.

Avatar de l’utilisateur
Spiriusis
Messages : 6
Inscription : 26 Oct 2018 15:30

Re: [DB-AL] Rebond calculé et précis d'un objet

Message par Spiriusis » 30 Oct 2018 21:32

Voilà, avec
  • En haut à droite "autojump1".
  • En bas à droite "autojump2"
  • En haut à gauche la modif x50 avec

    Code : Tout sélectionner

    v = (PlateformMove.plateformSpeed * 50) * Time.deltaTime;
    (ou on à toujours un décalage avec 60 ou autre valeur également)
  • En bas à gauche la modif x50 mais directement sur la variable plateformSpeed
https://www.youtube.com/watch?v=DkZ8ndwZtp8
(la vidéo est faite un peu à la vas vite)

Sinon, ben justement il n'y a pas de différence entre le autojump qui fonctionnait et maintenant, j'ai vérifier avec l'historique des sauvegardes cloud d'Unity (j'utilise le service "Collaborate"). Je vous met des captures d'écran des paramètres des objets, vu que ça ne peut que être du à des paramètres du projet (mais si on peut faire plus simple avec le nouveau script alors je laisserais bien tomber celui-là)

Merci de votre patience, parce que l'erreur est surement toute simple mais j'ai un peu de mal :)

Image

Image

Image

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

Re: [DB-AL] Rebond calculé et précis d'un objet

Message par Liven » 30 Oct 2018 23:24

Pour commencer un petit conseil pour faciliter le débuggage :

Si une variable n'est utilisée que dans le script en cours, ne la met pas en public, utilise plutôt le [SerializeField] si c'est juste histoire de la voir dans l'inspector.

Par exemple pour ta variable objectSpeed on ne sait pas si elle est modifiée par un autre script (logiquement non vu comment est construit ton code, mais pas moyen d'en être sûr).
Je sais que beaucoup de mec qui font des tutos ne prennent pas cette peine de le faire, mais je trouve que c'est une très mauvaise habitude et rend le dégogage galère.

Code : Tout sélectionner

public float objectSpeed;
// à remplacer par :
[SerializeField] private float objectSpeed;
// ou même juste (puisque les variables sont private  par défaut):
[SerializeField] float objectSpeed;
Sinon j'avoue que j'ai du mal à voir la logique de ton code. Je sais pas comment le dire autrement, mais je vois pas où tu vas (notament le time = (d / v)/2;).

En plus le fait d'avoir passé les mouvements en update (sur mon conseil j'avoue) t'as fait perdre le smooth de la montée et descente qu'il va falloir simuler avec des courbes... bref c'est peut être une fausse bonne idée.

Sinon un truc un peu sale, mais qui pourrais marcher est de revenir sur la version physics qui marchais le mieux et de checker à chaque rebond qu'on est bien à la bonne valeur z et corriger la position si on s'en éloigne trop.
C'est du bricolage, mais c'est souvent ça la prog.

Répondre

Revenir vers « (C#) CSharp »