I’m using the below code to clamp the rotation of my turret. It works fine on the right side, but when I get to the maximum clamp on the left side it resets to the right side instead of just stopping.
Vector3 dir = Input.mousePosition-new Vector3(Screen.width/2,Screen.height/2,0); // mouse direction relative to the middle of the screen
chaingun.right=Vector3.Slerp(chaingun.right,dir,5*Time.deltaTime); // Smoothly rotate towards the direction.
chaingun.eulerAngles=new Vector3(0,0,Mathf.Clamp(-Mathf.DeltaAngle(chaingun.eulerAngles.z,0),-150,0)); // Clamp.
//
Your best bet is to have local-only float variables to represent traverse and elevation, then change and clamp those floats, and finally drive .localRotation of the parts on their correct Transform axis.
Notes on clamping rotations and NOT using .eulerAngles because of gimbal lock:
How to instantly see gimbal lock for yourself:
All about Euler angles and rotations, by StarManta:
Then you just need to update the above two points based on your GameObjects, no need to fiddle with rotations. As long as you move those positions smoothly, the camera will be nice and smooth as well, both positionally and rotationally.
Unless you’re asking specifically about 2D physics please don’t use the 2D-Physics tag. This is scripting and Transform code which isn’t specific to 2D-physics.
I apologize for being lazy to fire up Unity on a Sunday, after I’ve been already working today because of a critical milestone.
If you’re still here tomorrow, I will attempt to recreate your scenario and show you what you can improve in your code and how to untangle these kinds of problems in general.
Vector3 dir = Input.mousePosition-new Vector3(Screen.width/2,Screen.height/2,0); // mouse direction relative to the middle of the screen
float angle=Vector3.SignedAngle(chaingun.parent.right,dir,chaingun.parent.forward);
chaingun.localRotation=Quaternion.Lerp(chaingun.localRotation,Quaternion.Euler(0,0,angle),5*Time.deltaTime);
chaingun.localEulerAngles=new Vector3(0,0,Mathf.Clamp(-Mathf.DeltaAngle(chaingun.localEulerAngles.z,0),-150,0)); // Clamp
That parameter is basically the rotation speed and so if you set it too high then your original problem will return where the gun quickly snaps from an angle of -150 to 0 as the cursor goes around the back of the chopper.
Your original code would probably have been okay if you had smoothly rotated the gun from its current direction to the target direction instead of just setting the rotation directly. Although your code would’ve rotated back to angle zero a little earlier than mine.
If you want the rotation to be a little snappier then instead of lerp you can use this:
Personally I like Lerp and Slerp because of the easing that the functions provide. Although some people don’t like using those functions in the way I use them because they think it’s not the way God intended for them to be used. But most of us don’t care…
Of course it’s deeper than that and has very little to do with God. Problem with lerp is that it’s frame-independent and so any ad-hoc animation made with it will vary in duration (among other problems). However, there is a way to tame it, here’s for example exponential decay
You probably meant frame rate dependent but yes, you’re right. But Lerp used with Time.deltaTime it’s good enough for most use cases. Although I wouldn’t recommend it for having a character jump across gaps but then I also wouldn’t recommend a character controller for the same reason as that is also not truly frame rate independent.