Trouble with transform.rotation with horizontal clamping?

I use horizontal clamp to restrict my camera movement when running on the side of walls/wall running. But I am having trouble getting the currentRotation of Quaternion.RotateTowards (line 6) to work. It only works when used in a trigger with the following line: emptyObject = other.transform.parent;. But I do not want to use OnTriggerEnter or OnCollisionEnter for wall running and everything but the clamp works perfectly.

Right now the clamp does not work at all. But if I change otherScript.emptyGameObject.rotation below from .rotation to .localRotation, the clamp works exactly how it should but only when I face a certain direction, otherwise the camera snaps to the xAngleClampValue of 25. The emptyObject is a child of my Player object and the Main Camera is also a child of my Player, and the camera script is stored in the Main Camera.

// Update()
Vector2 rotation = Vector2.zero;
float xAngleClampValue = 25f;

var yQuaternion = Quaternion.AngleAxis(yAxisRotation, Vector3.left);

Quaternion currentRotation = otherScript.emptyObject.rotation; // reference the Transform object from another script
Quaternion targetRotation = Quaternion.AngleAxis(xAxisRotation, Vector3.up);

var xQuaternion = Quaternion.RotateTowards(currentRotation, targetRotation, xAngleClampValue);
xAxisRotation = xQuat.eulerAngles.y;

transform.localRotation = yQuaternion;
playerObject.transform.rotation = xQuaternion;

There’s a bit more code missing but it just handles the Input.GetAxis() and sensitivity. There’s no other code linked to this besides the reference to the public Transform emptyObject; from the otherScript script.

Camera stuff is pretty tricky… you may wish to consider using Cinemachine from the Unity Package Manager.

There’s even a dedicated forum: Unity Engine - Unity Discussions

If you insist on making your own camera controller, the simplest way to do it is to think in terms of two Vector3 points in space: where the camera is LOCATED and where the camera is LOOKING.

private Vector3 WhereMyCameraIsLocated;
private Vector3 WhatMyCameraIsLookingAt;

void LateUpdate()
{
  cam.transform.position = WhereMyCameraIsLocated;
  cam.transform.LookAt( WhatMyCameraIsLookingAt);
}

Then you just need to update the above two points based on your GameObjects, no need to fiddle with rotations.

And then basically would I then use transform.eulerAngles inside of my current camera script to clamp WhatMyCameraIsLookingAt after I’ve stored it in transform.Lookat()?

You would do the math to clamp the look point BEFORE telling the camera to LookAt() it.

Generally, stay 100% away from .eulerAngles. Just don’t ever read or rely on them. Here’s why:

All about Euler angles and rotations, by StarManta:

https://starmanta.gitbooks.io/unitytipsredux/content/second-question.html

Thanks for the gitbooks link. I tested the sample code you provided on an empty project and I got it working perfectly (with no clamping).

I made changes to my camera code and added the transform.LookAt to it after clamping the horizontal rotation and the clamping feels smoother than my original code but the same issue exists where if I am not facing roughly the horizontal clamp rotation value that I have set, the camera will instantly flick in the opposite direction. The only thing I can think of is trying to normalize the angle and then apply that to my clamp.

Vector2 mouseDelta = new Vector2(Input.GetAxis(xAxis), Input.GetAxis(yAxis));

xAxisRotation += mouseDelta.x * sensitivity;
yAxisRotation += mouseDelta.y * sensitivity;

yAxisRotation = Mathf.Clamp(yAxisRotation, -90, 90);
xAxisRotation = Mathf.Clamp(xAxisRotation, -xAngleClampValue, xAngleClampValue); // -25 & 25f

this.transform.position = transform.position; // Get the position of the camera
transform.LookAt(otherScript.emptyObject); // Look at the object from the different script

var yQuaternion = Quaternion.AngleAxis(yAxisRotation, Vector3.left);
var xQuaternion = Quaternion.AngleAxis(xAxisRotation, Vector3.up);

transform.localRotation = yQuaternion;
playerObject.transform.rotation = xQuaternion;

Edit: I don’t think normalizing the angle made a difference

Solved