[DB][RESOLU] Bug translation de caméra saccadée (RaycastHit)

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
Slyback
Messages : 9
Inscription : 29 Oct 2020 21:27

[DB][RESOLU] Bug translation de caméra saccadée (RaycastHit)

Message par Slyback » 29 Oct 2020 23:20

Bonjour,

Premier post sur ce forum. J'apprends à développer sur Unity en C# en autodidacte depuis peu, et je suis confronté à un problème que je n'arrive pas à résoudre. Le script est assez basique, mais je ne comprends ce qu'il se produit dans Unity pour amener à ce résultat (voir vidéo).
Je cherche à déplacer la caméra à la façon d'un "cliqué déplacé", en calculant le mouvement depuis les coordonnées issues du RaycastHit sur le terrain.
Malheureusement ça ne fonctionne pas car cela entraine des mouvements saccadés de la caméra. Il n'y a pas de contrainte appliquée à la caméra, qui est libre et sans parent.

https://youtu.be/cyrrpI78gqQ

Est-ce que vous voyez d'où le problème peut venir ?

Code : Tout sélectionner

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

public class CameraController : MonoBehaviour
{
    Vector3 worldPositionStart;
    Vector3 worldPosition;
    Vector3 worldDirection;

    void Start ()
    {
        // Rigidbody camRigidbody = GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    void Update()
    {
        // Obtenir la position initiale de la cible dans l'espace
        if (Input.GetMouseButtonDown(0))
        { 
            Ray rayStart  = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitDataStart;
            Debug.Log("Clic gauche");

            if (Physics.Raycast(rayStart, out hitDataStart))
            {
                worldPositionStart = hitDataStart.point;
            }
        }

        // Obtenir la direction du mouvement dans l'espace
        if (Input.GetMouseButton(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitData;

            if (Physics.Raycast(ray, out hitData))
            {
                worldPosition = hitData.point;
            }
            worldDirection = worldPositionStart - worldPosition;
        }

        // Translation de la caméra
        this.transform.position = new Vector3(worldDirection.x, this.transform.position.y, worldDirection.z);
        Debug.Log(this.transform.position);
    }
}
Merci,
Dernière édition par Slyback le 30 Oct 2020 16:03, édité 1 fois.

Avatar de l’utilisateur
jmhoubre
Messages : 320
Inscription : 05 Oct 2019 22:05

Re: [DB] Bug translation de caméra saccadée (RaycastHit)

Message par jmhoubre » 30 Oct 2020 02:22

Bonsoir,
tu devrais regarder la documentation de LateUpdate ().

Slyback
Messages : 9
Inscription : 29 Oct 2020 21:27

Re: [DB] Bug translation de caméra saccadée (RaycastHit)

Message par Slyback » 30 Oct 2020 07:42

Merci.

J'ai mis la translation de la caméra dans la boucle LateUpdate () mais j'ai toujours le même problème.
J'ai également fait un test avec un plan simple (pour voir si cela venait des hex tiles), même problème.

Cela vient donc du script en lui-même. Quelque chose n'est pas bon ou ne fonctionne pas comme attendu :gene:

Les valeurs en X et Z alternent à chaque frame.

edit: l'erreur vient de cette boucle car worldPosition a une valeur qui alterne à chaque frame, ce qui produit la saccade :

Code : Tout sélectionner

        if (Input.GetMouseButton(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitData;

            if (Physics.Raycast(ray, out hitData))
            {
                worldPosition = hitData.point;
            }
        }
Pièces jointes
bug-coords.jpg
bug-coords.jpg (31.49 Kio) Consulté 157 fois

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 5505
Inscription : 28 Avr 2014 11:57
Localisation : Toulouse

Re: [DB] Bug translation de caméra saccadée (RaycastHit)

Message par boubouk50 » 30 Oct 2020 10:15

Je partirai sur le déplacement 2D (screenPosition) de la souris plutôt que la position World.
Vu que tu bouges ta caméra en même temps que la souris, le hitData.point n'est pas linéaire. Par exemple, si la caméra bouge plus vite que la souris, alors en allant vers la droite, le hitData.point suivant sera a gauche du précédent. Ainsi, ta caméra va aller a gauche, puis le suivant sera à droite (car la caméra aura bougé), il en résultera un effet "dans de scie".
Donc, au lieu de passer par le World Space, reste dans le Screen Space, et compare la position Screen de ta souris entre deux frames. Ainsi, le déplacement sera linéaire.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

Avatar de l’utilisateur
jmhoubre
Messages : 320
Inscription : 05 Oct 2019 22:05

Re: [DB] Bug translation de caméra saccadée (RaycastHit)

Message par jmhoubre » 30 Oct 2020 10:29

J'ai remplacé Input.GetMouseButton par Input.GetMouseButtonUp, et je n'ai plus le mouvement saccadé. Cela semble aller dans le sens de ce que t'indiques boubouk

Avatar de l’utilisateur
jmhoubre
Messages : 320
Inscription : 05 Oct 2019 22:05

Re: [DB] Bug translation de caméra saccadée (RaycastHit)

Message par jmhoubre » 30 Oct 2020 11:04

En relisant ton code avec le commentaire de boubouk en tête, j'ai légèrement modifié ton code pour ajouter à la position de la souris le déplacement à faire, puis mettre à zéro le déplacement.

Code : Tout sélectionner

using UnityEngine;

public class CameraController : MonoBehaviour
{
	private Vector3 mousePositionStart;
	private Vector3 mousePositionEnd;
	private Vector3 mouvement;

	void Update ()
	{
		// Obtenir la position initiale de la cible.
		if (Input.GetMouseButtonDown (0))
		{
			Ray rayStart = Camera.main.ScreenPointToRay (Input.mousePosition);
			RaycastHit hitDataStart;

			if (Physics.Raycast (rayStart, out hitDataStart))
			{
				mousePositionStart = hitDataStart.point;
			}
		}

		// Obtenir la translation à effectuer.
		if (Input.GetMouseButtonUp (0))
		{
			Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
			RaycastHit hitData;

			if (Physics.Raycast (ray, out hitData))
			{
				mousePositionEnd = hitData.point;
			}

			mouvement = mousePositionEnd - mousePositionStart;
		}

	}

	private void LateUpdate ()
	{
		// Translation de la caméra.
		transform.position -= mouvement;
		mouvement = Vector3.zero;
	}
}

Slyback
Messages : 9
Inscription : 29 Oct 2020 21:27

Re: [DB] Bug translation de caméra saccadée (RaycastHit)

Message par Slyback » 30 Oct 2020 11:44

Merci pour vos réponses, je comprends mieux le problème maintenant.

J'avais réalisé un script précédent utilisant effectivement le déplacement de la souris à l'écran pour donner les mouvements de la caméra. Le problème est qu'il ne prenait pas en compte l'éloignement de la cible du clic dans l'espace, et cela se ressentait dans le cliqué-glissé.

Il faut donc que je trouve une formule pour calculer l'éloignement de la cible du clic à chaque frame de façon calculée et non mesurée, en sachant que l'angle de vue de la caméra en perspective est fixe (35°) et que sa rotation et altitude y sont fixes également.

Pour ta solution jmhoubre, le problème c'est que Input.GetMouseButtonUp() ne donne qu'une seule valeur, et une fois que l'utilisateur a relaché le bouton. Or, il faut que la translation se fasse en temps-réel de manière fluide, quand l'utilisateur a encore le doigt sur le bouton.

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 5505
Inscription : 28 Avr 2014 11:57
Localisation : Toulouse

Re: [DB] Bug translation de caméra saccadée (RaycastHit)

Message par boubouk50 » 30 Oct 2020 12:06

Sinon, faire l'inverse.
A ton premier clic (down), tu récupères le point de Raycast.
Ensuite, tu fais en sorte que ce point reste sous la souris, donc un déplacement entre le point actuel et le point précédent.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

Slyback
Messages : 9
Inscription : 29 Oct 2020 21:27

Re: [DB] Bug translation de caméra saccadée (RaycastHit)

Message par Slyback » 30 Oct 2020 14:03

Je n'ai pas compris ce que tu proposes dans ton dernier commentaire boubouk50, il me semblait avoir fait ça dans mon code.

Après un peu de maths, j'ai trouvé la formule qui permet de calculer la profondeur :
y étant la valeur de hauteur du curseur à l'écran (comprise entre 0 et 1)
z étant la profondeur de l'espace visible à l'écran
altitude étant la hauteur de la caméra dans la scène
FOV étant le Field of View de la caméra

z = altitude / ( tan ( FOV * ( 1,5 - y ) ) )
Ainsi, zmin correspondrait à (y = 0) et zmax à (y = 1).

Dans mon cas, zmin ~ 26.92 et zmax ~ 112,90.

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 5505
Inscription : 28 Avr 2014 11:57
Localisation : Toulouse

Re: [DB] Bug translation de caméra saccadée (RaycastHit)

Message par boubouk50 » 30 Oct 2020 14:30

Dans ton premier script, tu faisais une affectation de la position de la caméra depuis le vecteur défini par le premier point défini par ton premier raycast et la position actuelle défini par le raycast en cours. Du coup, comme la caméra bougeait, la translation était "polluée" par ce mouvement. En gros ton code pouvait fonctionner si le calcul se faisait avec une caméra qui ne bougeait pas. (j'arrive pas trop à l'expliquer correctement désolé, disons que le mouvement de la caméra annule un peu la nouvelle position)
Je te propose, de déplacer la caméra via un Translate du vecteur entre la position en cours et la précédente pour calculer le delta qu'a fait ta souris en World Space, et donc éviter cette "pollution".
Ca rejoint ce que jmhoubre a fait dans son script avec le += sur la position.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

Répondre

Revenir vers « (C#) CSharp »