[DB-AL] Comment garder un mouvement avec une relation parent/enfant

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
Nath1849
Messages : 5
Inscription : 30 Déc 2020 11:25

[DB-AL] Comment garder un mouvement avec une relation parent/enfant

Message par Nath1849 » 30 Déc 2020 13:03

Bonjour, je commence sur Unity et pour mon premier projet j'essaye de faire un jeu en 2D où le joueur s'accroche à des plateformes qui tournent et appuie sur la touche espace pour s'en décoller ce qui devrait projeter le joueur.

Voici mon code qui permet d'attacher le joueur à une plateforme et de l'en détacher.

Code : Tout sélectionner

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

public class Parent : MonoBehaviour
{
    public GameObject player; //On recupere le game object Player
    public GameObject wheel; //On recupere le gameObject Wheel

    private void OnCollisionEnter2D(Collision2D other) { //On detecte la collision entre la wheel et autre
        player.transform.parent = wheel.transform; //Le game object wheel devient le parent du game object player
    }
    public void Update()
    {
         if (Input.GetButtonDown("Jump")) //Je prends l'input nommé "Jump" qui est de base assigné à la touche espace
        {
            player.transform.parent = null; //On détache le player de son parent
        }
    }
}
Le problème est qu'avec ce script lors du détachement du player il n'est soumis qu'à son propre poids et tombe, de plus quand le player est attaché à la plateforme tournante il ne reste pas collé, je pense que c'est à cause du rigidbody mais je ne suis pas sûr.

Je me demande donc si c'est la bonne manière d'attacher le player à la plateforme tournante et si je dois calculer un vecteur pour donner un mouvement au player.

Merci d'avoir lu et j'espère que quelqu'un pourra m'aider.

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

Re: [DB-AL] Comment garder un mouvement avec une relation parent/enfant

Message par Max » 30 Déc 2020 13:18

Bonjour,
Nath1849 a écrit :
30 Déc 2020 13:03
Je me demande donc si c'est la bonne manière d'attacher le player à la plateforme tournante et si je dois calculer un vecteur pour donner un mouvement au player.
Oui et oui.
Parenter la plateforme et le player est la bonne approche. Par contre, effectivement à ce moment là il faut que tu passes le RigidBody2D en Simulated = false.
Après lors de la séparation, il va te falloir calculer le vecteur correspondant à la force centripète pour déterminer la vélocité du RigidBody2D à appliquer à ton Player.
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

Nath1849
Messages : 5
Inscription : 30 Déc 2020 11:25

Re: [DB-AL] Comment garder un mouvement avec une relation parent/enfant

Message par Nath1849 » 30 Déc 2020 15:05

Bonjour,
Merci pour la réponse très rapide, j'ai essayé de modifier mon script de manière à appliquer tes conseils cependant je ne remarque aucune différence malgré le .addforce
Voici le script:

Code : Tout sélectionner

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

public class Parent : MonoBehaviour
{
    public GameObject player; //On recupere le game object Player
    public GameObject wheel; //On recupere le gameObject Wheel

    

    private void OnCollisionEnter2D(Collision2D other) //On detecte la collision entre la wheel et autre
    { 
        player.transform.parent = wheel.transform; //Le game object wheel devient le parent du game object player
        player.GetComponent<Rigidbody2D>().simulated = false; //On désactive le rigidbody
        
    }
    public void Update()
    {
         if (Input.GetButtonDown("Jump") && player.transform.IsChildOf(wheel.transform)) //S'active si le bouton espace est enfoncé et que le player est connecté a une wheel
        {
            float distance = Vector2.Distance(player.transform.position, wheel.transform.position); //On calcule la distance entre le joueur et la wheel.
            player.transform.parent = null; //On detache le player de son parent
            player.GetComponent<Rigidbody2D>().simulated = true; //On réactive le rigidbody
            player.GetComponent<Rigidbody2D>().AddForce(player.GetComponent<Rigidbody2D>().velocity/distance); //On ajoute la force centripète que l'on calcule 
            //avec la masse, la vélocité et la distance avec la masse = 1
        }
    }
}
Unity ne ressort aucune erreur donc je ne sais pas si je me suis trompé dans la formule ou dans le code.
Merci

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

Re: [DB-AL] Comment garder un mouvement avec une relation parent/enfant

Message par Max » 30 Déc 2020 15:27

En fait tu appréhendes mal l'utilisation de certains paramètres.
Pour un soucis de clarté (et d’optimisation), met en cache ton Player.RigidBody2D
(exemple dans Start() rb2DPlayer = player.GetComponent<Rigidbody2D>();).
En suite, il ne faut pas te servir de la vélocité de ton Player pour établir sa force, mais c'est cette donnée qu'il faut modifier. Genre rb2DPlayer.velocity = unVector2, vecteur lié au calcul de la force, basé sur la distance entre le Player et le centre de la roue, mais aussi de la rotation de celle-ci (l'angle et si on veut aller au bout, la vitesse angulaire).
En suite, attention à ton Trigger sur ta roue, car au moment de l'ejection calculé de ton Player, il peut éventuellement perturber son fonctionnement (et du coup re-parenter le Player à la roue).
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

Nath1849
Messages : 5
Inscription : 30 Déc 2020 11:25

Re: [DB-AL] Comment garder un mouvement avec une relation parent/enfant

Message par Nath1849 » 30 Déc 2020 17:55

Max a écrit :
30 Déc 2020 15:27
En suite, il ne faut pas te servir de la vélocité de ton Player pour établir sa force, mais c'est cette donnée qu'il faut modifier. Genre rb2DPlayer.velocity = unVector2, vecteur lié au calcul de la force, basé sur la distance entre le Player et le centre de la roue, mais aussi de la rotation de celle-ci (l'angle et si on veut aller au bout, la vitesse angulaire).
Désolé de continuer a déranger mais je n'arrive pas à trouver une formule pour ce vecteur, je pense pouvoir obtenir l'angle de la roue avec un .rotation sur le rigidbody de la roue mais je ne vois vraiment pas comment l'utiliser, de plus en changeant la velocité dans le script j'ai l'impression qu'elle devient constante dans la scene, ne faudrait il donc pas que je rajoute juste une force pour que le poids agisse aussi ?
En suite, attention à ton Trigger sur ta roue, car au moment de l'ejection calculé de ton Player, il peut éventuellement perturber son fonctionnement (et du coup re-parenter le Player à la roue).
Quant à ce problème ci je n'ai pas d'idées non plus, je suis preneur pour n'importe quelle idée
Et encore désolé pour le derangement.

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

Re: [DB-AL] Comment garder un mouvement avec une relation parent/enfant

Message par Max » 30 Déc 2020 19:02

Déjà, concernant la roue, dans la mesure où c'est un élément de décor (même mobile), il ne devrait pas posséder de RigidBody.
Concernant la vélocité, tu peux établir un vecteur de base dont la composante 'y' serait la distance Player/Roue, genre vector2fc = new Vector2(0, distance);, puis, tu appliques une rotation à ce vecteur lié à la rotation de la roue
(exemple from scratch-> vector2fc = Quaternion.Euler(0f, 0f, wheel.transform.rotation.eulerAngles.z) * vector2fc; et tu peux peaufiner en appliquant un facteur multiplicateur à ce vecteur lié à la vitesse de la roue.

Une fois ton vecteur calculé, tu fais un rb2DPlayer.velocity = vector2fc;. Cette initialisation de la vélocité ne dois se faire qu'au moment du saut, pour qu'après ton Player, moyennant sa physique, garde un comportement cohérent.

Concernant le Trigger, j'ai peur qu'au moment du saut, il y ai encore un appel à OnCollisionEnter2D(). Le mieux est de désactiver le Collider de la roue (au moins temporairement) pour éviter ce genre d'interférence entre le Player et la roue.
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

Nath1849
Messages : 5
Inscription : 30 Déc 2020 11:25

Re: [DB-AL] Comment garder un mouvement avec une relation parent/enfant

Message par Nath1849 » 03 Jan 2021 13:41

J'ai adapté mon script à tes recommandations et j'obtiens une ejection cependant cette ejection n'est pas orienté dans le bon sens : Voici une vidéo

https://youtu.be/cn8QIBKWR0E

Et le script modifié :

Code : Tout sélectionner

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

public class Parent : MonoBehaviour
{
    public GameObject player; //On recupere le game object Player
    public GameObject wheel; //On recupere le gameObject Wheel
    private Rigidbody2D rb2DPlayer;
    private Vector2 vector2fc;

    public void Start() 
    {
        rb2DPlayer = player.GetComponent<Rigidbody2D>();
    }

    private void OnCollisionEnter2D(Collision2D other) //On detecte la collision entre la wheel et autre
    { 
        player.transform.parent = wheel.transform; //Le game object wheel devient le parent du game object player
        rb2DPlayer.simulated = false; //On désactive le rigidbody
        
    }
    public void Update()
    {
         if (Input.GetButtonDown("Jump") && player.transform.IsChildOf(wheel.transform)) //S'active si le bouton espace est enfoncé et que le player est connecté a une wheel
        {
            float distance = Vector2.Distance(player.transform.position, wheel.transform.position); //On calcule la distance entre le joueur et la wheel.
            vector2fc = new Vector2(0, distance);
            vector2fc = Quaternion.Euler(0f, 0f, wheel.transform.rotation.eulerAngles.z) * vector2fc;
            Debug.Log(vector2fc);
            wheel.GetComponent<CircleCollider2D>().enabled = false; //Je désactive le collider de la roue pour empecher qu'elle rattrappe le joueur directement
            player.transform.parent = null; //On detache le player de son parent
            rb2DPlayer.simulated = true; //On réactive le rigidbody
            rb2DPlayer.velocity = vector2fc * 2;//Je multiplie le vecteur pour que le résultat soit facilement visible
            //wheel.GetComponent<CircleCollider2D>().enabled = true; //Je réactive le collider de la roue après l'ejection, je l'enleve car il est trop rapide pour le moment.
        }
    }
}
Et merci de m'aider sur mon projet.

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

Re: [DB-AL] Comment garder un mouvement avec une relation parent/enfant

Message par Max » 03 Jan 2021 15:13

Hello,

je pense que la source de ton soucis est liée au fait qu'au moment où ton Player s'accroche à la roue, celle-ci à un angle qui n'est pas égale à zéro (ce qui parait logique vu quelle tourne).
Il faut trouver la solution pour contourner ce soucis, soit tu comptes par le biais d'un paramètre supplémentaire la rotation de la roue uniquement au moment de l'encrage, ou tu peux aussi mémoriser la valeur de rotation de la roue au moment de l'encrage pour le soustraire à wheel.transform.rotation.eulerAngles.z au moment du calcul de la rotation du vecteur d’inertie.
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

Nath1849
Messages : 5
Inscription : 30 Déc 2020 11:25

Re: [DB-AL] Comment garder un mouvement avec une relation parent/enfant

Message par Nath1849 » 17 Jan 2021 17:57

Bonjour,
J'ai réfléchis à tes suggestions et je me suis aperçu que cela me permettrait d'avoir la différence entre les deux angles de la roue soit, de combien de degré elle a tourné cependant je cherche pour ce problème l'angle où se trouve le joueur au moment du saut, il me faut donc savoir l'angle auquel il y a eu collision entre le player et la roue.
De plus vu que le player roule et tourne avec la roue ne faudrait il pas rajouter une ligne telle que

Code : Tout sélectionner

vector2fc = Quaternion.Euler(0f,0f,360-player.transform.EulerAngles.z)*vector2fc
Pour prendre en compte la rotation du joueur.
Il y a t'il un moyen de trouver l'angle de collision sur Unity et est-ce que cette dernière ligne est utile ?
Merci

Répondre

Revenir vers « (C#) CSharp »