Voilà pas mal de temps que je cherche une solution pour un détail qui tarabuste.
Je me suis créé un petit outil pour gérer les rotations avec la souris comme avec une manivelle.
Cet outil me permet d'orienter ma manivelle dans les 3 directions, et les objets reliés pivotent selon l'orientation de ma manivelle.
Je clique sur ma manivelle, et je fais tourner mon curseur dans un sens ou dans l'autre selon mon désir et jusque là tout va bien.
Mon soucis est que quand je lâche ma manivelle, et que j'y reviens dessus, mes objets ont un sursaut pour s'aligner par rapport à la nouvelle position de ma souris, ce comportement et normal, en fait, compte tenu de la programmation, mais je voudrais éviter ce sursaut, et c'est là que je fais appel à votre perspicacité, car je n'arrive pas à trouver une solution.
Voici mon code:
Code : Tout sélectionner
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class Test : MonoBehaviour
{
public enum ModeRotation
{
Forward,
Right,
Up
}
public Camera Camera;
public List<Transform> APivoter;
public ModeRotation modeRotation = ModeRotation.Up;
Transform Objet;
List<Vector3> ExRot;
private void Start()
{
Objet = transform.GetChild(0);
}
bool run;
private void Update()
{
if(!run)
{
run = Application.isPlaying;
if (modeRotation == ModeRotation.Forward)
transform.eulerAngles = new Vector3(90, 0, 0);
else if (modeRotation == ModeRotation.Up)
transform.eulerAngles = new Vector3(0, 0, 0);
else if (modeRotation == ModeRotation.Right)
transform.eulerAngles = new Vector3(0, 0, 90);
}
if (modeRotation == ModeRotation.Forward)
{
if (Input.GetMouseButton(0))
{
Vector3 pos = RaycastPos(Camera, transform);
if (pos != Vector3.zero)
{
pos.z = Objet.position.z;
Vector3 targetDir = pos - transform.position;
float angleBetween = Vector3.SignedAngle(Objet.up, targetDir, Vector3.forward);
Objet.Rotate(Objet.forward, angleBetween);
for (int i = 0; i < APivoter.Count; i++)
{
APivoter[i].Rotate(APivoter[i].forward, angleBetween);
}
}
}
}
else if (modeRotation == ModeRotation.Up)
{
if (Input.GetMouseButton(0))
{
Vector3 pos = RaycastPos(Camera, transform);
if (pos != Vector3.zero)
{
pos.y = Objet.position.y;
Vector3 targetDir = pos - transform.position;
float angleBetween = Vector3.SignedAngle(Objet.forward, targetDir, Vector3.up);
Objet.Rotate(Objet.up, angleBetween);
for (int i = 0; i < APivoter.Count; i++)
{
APivoter[i].Rotate(APivoter[i].up, angleBetween);
}
}
}
}
else if (modeRotation == ModeRotation.Right)
{
if (Input.GetMouseButton(0))
{
Vector3 pos = RaycastPos(Camera, transform);
if (pos != Vector3.zero)
{
pos.x = Objet.position.x;
Vector3 targetDir = pos - transform.position;
float angleBetween = Vector3.SignedAngle(Objet.up, targetDir, Vector3.right);
Objet.Rotate(Objet.right, angleBetween);
for (int i = 0; i < APivoter.Count; i++)
{
APivoter[i].Rotate(APivoter[i].right, angleBetween);
}
}
}
}
}
public Vector3 RaycastPos(Camera camera, Transform objet)
{
//on envoie le rayon vers la position de la souris
Ray ray = camera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
//s'il rencontre l'objet
if (hit.transform == objet)
{
//retourne la position du clic;
return hit.point;
}
}
return Vector3.zero;
}
}
mettre le script sur cet empty.
Enfant de cet empty mettre un Cube (par exemple, mais sans collider pour ne pas qu'il gêne) pour prendre les commandes. Ça peut être un empty aussi. mais avec un cube on peut contrôler l'effet des commandes.
D'autres objets peuvent être reliés à la propriété "APivoter", ce sont eux en fait les cibles de la rotation.
Voilà, près pour les tests.
On peut changer la direction de la manivelle en changeant le "ModeRotation"
En mode run, cliquer et draguer en tournant sur le cube, il doit pivoter.
si vous relachez le clic et que vous recommencez à partir d'une autre position, le cube et les objets se mettent en place par rapport au nouveau clic, c'est ce qui me dérange.
Si vous quelqu'un avait une idée pour régler ce détail, ce serait sympa.