[RESOLU] [DB-AL] Rigidbody.AddForce fait ce déplacer deux objet au lieu d'un seul
Publié : 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 :
ps : les directives using que j'utilise sont celle qu'Unity déclare par défaut quand il crée un nouveau script.
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);
}
}
Code : Tout sélectionner
using System.Collections;
using System.Collections.Generic;
using UnityEngine;