Clamping rotation between two angles
I'm working on kind of an infinite runner type game. I have seen this answer: http://answers.unity3d.com/questions/1409655/how-to-clamp-rotation-between-negative-and-positiv.html but it does not work for me (the car rotates too far to the right and does not rotate at all to the left).
I'm trying to keep an object that is chasing the player within 7 degrees of 0 (so minimum Euler is (0, -7,0) and max is (0, 7, 0)). It only needs to rotate on the Y axis. Basically, when it is moving left to follow the player I want it to quickly approach the left angle (-7) and vice versa for the right instead of just snapping to +/- 7.
I've tried using Quaternion.Lerp and Slerp but they had the same issue as the answer I found so I'm thinking something could be wrong with my angle math.
To keep things simple in my code I have a function that is passed a float. If the float is 0 it just sets the rotation to Quaternion.identity, otherwise it (is supposed to) turn the object according to whether or not the float is positive or negative.
This is my function:
//MaxAngleY is 7, turnAmt is either 0 or +/- ~500 (sidespeed is 500)
public void AngleBasedOnTurn(float turnAmt)
{
float turnSpeed = 5f;
if (turnAmt == 0)
{
transform.rotation = Quaternion.identity;
return;
}
//amt is always going to be 7 or -7, it is correctly showing up as -7 when car is turning to left
float amt = MaxAngleY * (turnAmt / SideSpeed);
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0, amt, 0), Time.deltaTime * turnSpeed);
}
Quaternion.Lerp has had the best results. The problem is it works fine to angle the car to one side but then has problems angling it back to the other side. I have a quick video demonstrating this here: https://www.youtube.com/watch?v=K0NPXUV8JUY
What am I doing wrong?
You don't show us how you calculate turnAmt. if turn amount is always == to SideSpeed: then (turnAmt / SideSpeed)
; will always be +1, and never be -1.
turnAmt can be negative (that's poor phrasing on my part), so turnAmt/SideSpeed can be +1 or -1. turnAmt is just the sideways force applied to the rigidbody.
amt is being calculated correctly, I verified with some Debug.Log's
I'm trying to keep an object that is chasing the player within 7 degrees of 0 (so $$anonymous$$imum Euler is (0, -7,0) and max is (0, 7, 0)).
I suspect this concept is the issue. What if the target is outside of that 14 degree arc?
$$anonymous$$ay I suggest you ins$$anonymous$$d apply a $$anonymous$$axTurnRate ins$$anonymous$$d:
Quaternion $$anonymous$$axTurnRate = Quaternion.Euler(0, 7, 0); //number of degrees per sec
float oneOr$$anonymous$$inusOne = (turnAmt / SideSpeed);
transform.rotation *= (oneOr$$anonymous$$inusOne * Time.deltaTime) * $$anonymous$$axTurnRate; //multiplying two quaterions effectively applies one rotatation to another (adds em)..
That has a more desirable effect but it's still turning pretty far. I changed some things up in the code because you brought up a good point about being outside of range. I now froze rotation completely and the function now unfreezes Y rotation and then freezes it again at the end to get rid of any external factors.
I think what I'm going to do (since I only need rotation on one axis and other functions are designed to work with all 3) is manually increase or decrease a float and keep that float on the range of [-7, 7] and then set the Euler Y to the float and see how that goes.
Yup, that worked, thanks for pointing me in the right direction!
Your answer
Follow this Question
Related Questions
How to use Quaternion.Slerp with transform.LookAt? 3 Answers
3 Axis Camera Rotation 0 Answers
Questions about Rotations in unity 1 Answer
Quaternion.RotateTowards for camera positions is buggy 1 Answer
Transform.Rotate with dynamic values 1 Answer