Home > OS >  Problem to rotate Quaternion on two axes with reference to a plane in Unity
Problem to rotate Quaternion on two axes with reference to a plane in Unity

Time:10-20

I have only been able to rotate it in the x axis but I would also like to do it in the z with the movement of the mouse. Sorry for the mistakes is google translator.

[SerializeField] private float camRotationAmount = 0.2f;
public Quaternion newRotation;


newRotation *= Quaternion.Euler(Vector3.up * Input.GetAxis("Mouse X"));

transform.rotation = Quaternion.Lerp(transform.rotation, newRotation, Time.deltaTime * camSmoothness);

I would like to add Input.GetAxis ("Mouse Y") for Vector3.left without tilting the camera. it's for a rts game. Thanks

CodePudding user response:

In general you will want to separate the Y and X rotation the following way:

  • rotate around Y in global space
  • rotate around X in local space.

Whether you do this purely by logic or using a parent-child hierarchy is up to you ... second is easier to understand in my opinion.


Using the Hierarchy

There you would simply have a hierarchy like e.g.

CameraAnchor
|--Camera

and have a script on the CameraAnchor like e.g.

public class CameraAnchorController : MonoBehaviour
{
    public float cameraSmoothness = 5f;

    private Quaternion targetGlobalRotation;
    private Quaternion targetLocalRotation;

    private Transform child;

    private void Start()
    {
        child = transform.GetChild(0);

        targetGlobalRotation = transform.rotation;
        targetLocalRotation = transform.GetChild(0).localRotation;
    }

    private void Update()
    {
        targetGlobalRotation *= Quaternion.Euler(Vector3.up * Input.GetAxis("Mouse X"));
        targetLocalRotation *= Quaternion.Euler(Vector3.right * -Input.GetAxis("Mouse Y"));

        var lerpFactor = cameraSmoothness * Time.deltaTime;

        transform.rotation = Quaternion.Lerp(transform.rotation, targetGlobalRotation, lerpFactor);
        child.localRotation = Quaternion.Lerp(child.localRotation, targetLocalRotation, lerpFactor);
    }
}

Using Quaternion math

As said you could do the same thing in one single object but I would still keep both rotations separated:

public class CameraController : MonoBehaviour
{
    public float cameraSmoothness = 5f;

    private Quaternion targetGlobalRotation;
    private Quaternion targetLocalRotation = Quaternion.Idendity;

    private void Start()
    {
        targetGlobalRotation = transform.rotation;
    }

    private void Update()
    {
        targetGlobalRotation *= Quaternion.Euler(Vector3.up * Input.GetAxis("Mouse X"));
        targetLocalRotation *= Quaternion.Euler(Vector3.right * -Input.GetAxis("Mouse Y"));

        transform.rotation = Quaternion.Lerp(transform.rotation, targetGlobalRotation * targetLocalRotation, cameraSmoothness * Time.deltaTime);
    }
}

Now why does this work when we are still using Vector3.right now?

By doing targetGlobalRotation * targetLocalRotation we first rotate around the global Y axis and then apply the rotation on the X axis based on this already applied rotation -> it is now an additional local rotation!

  • Related