Rex Tool
Rex Tool

Reputation: 35

Clamp a quaternion rotation in unity

I have this code but I have not been able to find a decent solution to clamp the X axis between 2 angle values. How would it be done in this case?

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

    private Quaternion targetGlobalRotation;
    private Quaternion targetLocalRotation = Quaternion.Identity;

    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);
    }
}

Upvotes: 1

Views: 9639

Answers (3)

KYL3R
KYL3R

Reputation: 4073

Clamp rotation on all axes, like limiting the Head-Rotation to avoid that "owl" move. Let's say the looking-target is behind you - you want to look over your shoulder, but not turn further. So we limit the angle relative to the transforms (forward) rotation.

Vector3 directionToTarget = transform.position - target.position;
Quaternion targetRot = Quaternion.LookRotation(directionToTarget);
Quaternion clampedTargetRot = Quaternion.RotateTowards(transform.rotation, lookRotation, 90f);
headTransform.rotation = clampedTargetRot;

Limiting to 90° means the head could go left or right, so the overall movement range is 180°.

enter image description here

Upvotes: 2

Nezdanchick
Nezdanchick

Reputation: 11

You need to Clamp Mouse Y + transform.rotation.x like this

    _mouseX += Input.GetAxis("Mouse X") * _horizontalSensitive;
    _camera.transform.localRotation = Quaternion.Euler(0, _mouseX, 0);

    _mouseY -= Input.GetAxis("Mouse Y") * _verticalSensitive;
    _mouseY = Mathf.Clamp(_mouseY, -90, 90);
    _camera.transform.localRotation = Quaternion.Euler(_mouseY, 0, 0);

PS: _camera represent any gameobject on your scene

Upvotes: 0

derHugo
derHugo

Reputation: 90659

For this you would rather use Euler angles and only convert them to Quaternion after applying the clamp!

Never directly touch individual components of a Quaternion unless you really know exactly what you are doing! A Quaternion has four components x, y, z and w and they all move in the range -1 to 1 so what you tried makes little sense ;)

It could be something like e.g.

// Adjust via Inspector
public float minXRotation = 10;
public float maxXRotation = 90;

// Also adjust via Inspector
public Vector2 sensitivity = Vector2.one;

private float targetYRotation;
private float targetXRotation;

private void Update()
{
    targetYRotation += Input.GetAxis("Mouse X")) * sensitivity.x;      
    targetXRotation -= Input.GetAxis("Mouse Y")) * sensitivity.y;

    targetXRotation = Mathf.Clamp(targetXRotation, minXRotation, maxXRotation);

    var targetRotation = Quaternion.Euler(Vector3.up * targetYRotation) * Quaternion.Euler(Vector3.right * targetXRotation);

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

Upvotes: 3

Related Questions