[RESOLU] [DB-AL] Rigidbody.AddForce fait ce déplacer deux objet au lieu d'un seul

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
SignéA
Messages : 7
Inscription : 05 Nov 2019 11:06
Contact :

[RESOLU] [DB-AL] Rigidbody.AddForce fait ce déplacer deux objet au lieu d'un seul

Message par SignéA » 06 Nov 2019 13:21

Bonjour ! Je voudrais que quelqu'un m'aide à résoudre mon problème.

Résumer de la situation : Bon voilà, je suis entrain de faire le cours "Create with code" de Unity Learn et je suis arrivée au Lab4, l'avant-dernier exercice du projet personnelle à réaliser avant la dernière leçon du cours.

J'ai planifié mon projet personnelle... Un jeu de plateforme combiner avec un endless runner en vue de côté (la caméra est en mode orthographique) avec des modèles en 3D, où le joueur doit éviter des plateformes en mouvements qui apparaissent à droite de l'écran, traversent la scène jusqu'à disparaître à gauche de l'écran une fois sortie du champ de vision de la camera. Mon joueur lui, qui est représenté par un cube, peut sauter, avancer et reculer. Quand il est dans les airs il peut légèrement contrôler sa trajectoire pour mieux ce réceptionner sur la plateforme suivante, ceci est un comportement que je n'avais pas bien définie à la planification du projet mais que j'ai trouvé intéressant, donc je l'ai gardé et amélioré pour être plus contrôlable et moins dû au fruit du hasard.

Dû coup, j'ai créer un nouveau projet Unity, mis en place les primitives pour le prototypage et écrit le script du joueur, le "PlayerController". Le game object "Player" à un composant Rigidbody car j'en ai besoin pour utilisé la gravité donc je déplace le cube qui représente le joueur avec playerRb.AddForce().

Maintenant je suis en train de programmer le gameplay de base, les plateformes qui doivent apparaître à droite et se déplacer vers la gauche à l'aide de la méthode AddForce de leur rigidbody. Le déplacement d'une plateforme est programmé dans le script "MoveLeft" qui lui est appliqué en tant que component.

Le problème :
Quand je test mon jeu et fait monter mon cube sur une plateforme, ce n'est plus mon cube seulement qui bouge quand j'appuie sur la flèches droite et la flèche gauche mais la plateforme aussi. Et quand je saute, donc, quand je ne suis plus en contact avec la plateforme, elle recommence à se déplacer vers la gauche comme cela est prévu dans son script.

J'ai essayé de changer les conditions qui modifiait la variable isOnGrounded, car au début elle était modifier uniquement quand le joueur sautait et retombait au sol mais quand je ne sautais pas et tombait d'une plate-forme isOnGrounded restait sur true, ce qui faisait que le joueur pouvais sauter et se déplacer dans les airs à une grande vitesse, peut-être à cause d'un manque de résistance avec l'air. Alors j'ai du faire de nombreux essaie jusqu'à ce que je trouve l'astuce d'utiliser OnCollisionStay() et OnCollisionExit() pour tester si l'objet est sur le sol ou dans les airs, en chute libre.

Et au final tout fonctionnait, avant que je fasse bouger la plateforme avec là encore, AddForce. Au part avant j'avais déjà essayé de la déplacer sans physique, avec la méthode transform.Translate() mais celui-ci n'étant pas fait pour fonctionner dans tout les cas avec un autre objet qui subi la physique, cette solution me donna de mauvais résultats de collision. À la fin je finis même par appeler la méthode physic.Raycast() pour tester ma collision avec le sol mais le problème ne semble pas venir de là.

J'ai aussi essayé de changer les contraintes physiques de mon "Player", le cube, qui devait
normalement ne pas avoir de rotation et ne pas se déplacer sur l'axe z mais que dans le plan (X, Y). Mais là aussi rien à changer il y a toujours le même problème.

Par contre le saut lui, il fonctionne dans toutes les situations que j'ai pu vous citer plus haut.

J'ai cherché sur le net et sur votre forum mais je n'ai trouvé aucun cas similaire à mon problème, à part des questions sur comment bouger un personnage avec une plateforme mobile, et la plus part du temps il était suggéré de faire le joueur devenir un parent de la plateforme pendant tout le temps qu'il restera dessus et de le faire se déplacer en utilisant ses coordonnées locales. Est-ce cela que je doit faire ? Car je l'est essayé et rien n'a faire, c'est toujours la même chose qui ce produit.

Question : Pourquoi ma plateforme bouge quand j'appuie sur les touches directionnelles alors qu'elle ne possède pas le script "PlayerController" comme component ?

Je voudrais pouvoir aller à l'opposé de la direction de la plateforme sans qu'elle ne soit embarquée avec moi comme dans les jeux Mario bros où les plateformes mobile font leur affaire pendant que Mario lui, marche dessus et saute sur d'autres plateformes pour continuer à avancer.

Voici le code des scripts "PlayerController" et "MoveLeft" pour que vous puissiez comprendre mon problème et peut-être trouver l'erreur que j'ai peut-être fait :

Code : Tout sélectionner

public class PlayerController : MonoBehaviour
{
    // Contrôle la vitesse de déplacement du joueur sur terre et ses capacités à planer dans les air
    public float speed = 700.0f;
    public float flySpeed = 200.0f;
    
    // Permet de Contrôler la puissance de l'impulsion que prend le joueur pour sauter
    public float jumpForce = 80.0f;

    // La variable de vérification pour les testes de collision avec le sol
    private bool isOnGrounded = true;

    // la position sur l'axe X du mur invisible de droite
    private float xBound = 24;

    private Rigidbody playerRb;

    // Start is called before the first frame update
    void Start()
    {
        // Récupère le composant Rigidbody attaché au Player
        playerRb = GetComponent<Rigidbody>();
    }
    
    // Update is called once per frame
    void FixedUpdate()
    {
        // Appelle la méthode qui gère les déplacements du joueur
        MovePlayer();

        // Appelle la méthode qui gère l'apparition des murs invisible
        ConstrainPlayerPosition();
    }

    // vérifie si le joueur est sur le sol 
    private void OnCollisionStay(Collision collision)
    {
        if(collision.gameObject.CompareTag("Platform"))
        {
            isOnGrounded = true;
        }
    }

    // Vérifie si le joueur est dans les air
    private void OnCollisionExit(Collision collision)
    {
        if (collision.gameObject.CompareTag("Platform"))
        {
            isOnGrounded = false;
        }
    }

    // Permet au joueur de bouger à l'aide des touches directionnelles et de la barre d'espace 
    void MovePlayer()
    {
        // Récupère l'entré au clavier de l'utilisateur
        float horizontalInput = Input.GetAxis("Horizontal");

        // Bouge le personnage vers la droite ou vers la gauche avec la flèche droite et la flèche gauche quand il n'est pas accroché au rebord d'une plateforme
        if (isOnGrounded)
        {
            playerRb.AddForce(Vector3.right * speed * horizontalInput * Time.fixedDeltaTime);
        }
        else if(!isOnGrounded)
        {
            playerRb.AddForce(Vector3.right * flySpeed * horizontalInput * Time.fixedDeltaTime);
        }

        // Fait le personnage sauter quand le joueur appuie sur la barre d'espace et que le personnage est au sol
        if (Input.GetKeyDown(KeyCode.Space) && isOnGrounded)
        {
            playerRb.AddForce(Vector3.up * jumpForce * Time.fixedDeltaTime, ForceMode.Impulse);
        }
    }

    // Empêche au joueur de sortir du champ de vision de la camera
    void ConstrainPlayerPosition()
    {
        // Crée un mur invisible au bord gauche de l'écran
        if (transform.position.x < -xBound)
        {
            transform.position = new Vector3(-xBound, transform.position.y, transform.position.z);
        }

        // Crée un mur invisible au bord droit de l'écran
        if (transform.position.x > xBound)
        {
            transform.position = new Vector3(xBound, transform.position.y, transform.position.z);
        }
    }
}

Code : Tout sélectionner

public class MoveLeft : MonoBehaviour
{
    // La vitesse de déplacement de la plateforme
    public float speed = 100.0f;

    private Rigidbody platformRb;

    // Start is called before the first frame update
    void Start()
    {
        // Récupère le composant Rigidbody attaché à la plateforme
        platformRb = GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        // Déplace la plateforme vers la gauche
        platformRb.AddForce(Vector3.left * speed * Time.fixedDeltaTime);
    }

    // Une tentative de ma part de forcer la plateforme à avancer malgré le fait qu'elle soit stoppé par le joueur
    private void OnCollisionStay(Collision collision)
    {
        if(collision.gameObject.CompareTag("Player"))
        {
            KeepMoving();
        }
    }

    // Reprend le code présent dans FixedUpdate pour l'appliqué en cas de collision avec le joueur
    void KeepMoving()
    {
        platformRb.AddForce(Vector3.left * speed * Time.fixedDeltaTime);
    }
}
ps : les directives using que j'utilise sont celle qu'Unity déclare par défaut quand il crée un nouveau script.

Code : Tout sélectionner

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
Dernière édition par SignéA le 19 Nov 2019 01:14, édité 1 fois.

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

Re: [DB-AL] Rigidbody.AddForce fait ce déplacer deux objet au lieu d'un seul

Message par Max » 06 Nov 2019 16:46

Re,

Comment est constitué ton level ? Je vois que tu as des RigidBody sur tes plateformes. Ce qui laisse penser qu'elle ont tendance à chuter (comme ton Player). Comment sont-elles configurées ? Elles ne sont visiblement pas en IsKinematic vue que tu emplois AddForce.
Après d'instinct, je dirais qu'un Player(Cube) posé sur une plateforme (autre cube) à tendance, par friction, à entrainer l'autre tant qu'il y a contact...
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

SignéA
Messages : 7
Inscription : 05 Nov 2019 11:06
Contact :

Re: [DB-AL] Rigidbody.AddForce fait ce déplacer deux objet au lieu d'un seul

Message par SignéA » 07 Nov 2019 00:15

Merci, c'est bon ! S'était bien un problème de friction ! J'ai retirer la contrainte de rotation sur l'axe Z pour tester et la plateforme était malheureusement toujours entrainer par le cube, alors comme je m'était souvenu que dans le cours le tuteur suggérait d'utiliser une sphère pour représenter le joueur, j'ai carrément remplacer le cube par une sphère et je lui ai mis les même composants et paramètre que le cube, à la différence que j'ai laissé la checkbox de contrainte sur l'axe Z décoché. J'ai testé et ça fonctionne. :super:

Tout comme les pneus de la voiture entraine le chassie avec lui à cause de la friction, le cube et en générale l'objet le plus puissant en terme de vitesse (direction * vitesse), entraine le plus faible, là aussi à cause de la friction. La friction est plus présente que je ne le croyais et me fait penser que je devrais l'étudier même si je ne crée pas de jeu de voiture.

Et au fait, j'ai dû créer un Physic Material "Slide" pour mettre au collider de la plateforme et de la sphère afin d'enlever toute friction entre les deux, comme ça elle n'est pas ralentit par la sphère qui avance ou recule en même temps qu'elle ce déplace vers la gauche. Le physic Material est réglé avec 0 de friction dynamique et en mode combinaison de Friction : Multiplier.

SignéA
Messages : 7
Inscription : 05 Nov 2019 11:06
Contact :

Re: [DB-AL] Rigidbody.AddForce fait ce déplacer deux objet au lieu d'un seul

Message par SignéA » 07 Nov 2019 00:38

Mais il semblerait qu'il n'ont pas besoin de ça pour fonctionner.

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

Re: [DB-AL] Rigidbody.AddForce fait ce déplacer deux objet au lieu d'un seul

Message par Max » 07 Nov 2019 08:40

Bonjour,

attention, trop de glissement peut aussi t'amener à des effets indésirables dans d'autre situations de jeu.
Sinon à titre d'info, dans le StandardAssets tu as des exemples de définition de base de PhysicMaterial:

Image
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


Répondre

Revenir vers « (C#) CSharp »