I've done an if / else with the final position / rotation plus they never complete, how can I check this? stays like this
https://i.imgur.com/3cQ9AEk.gif
if(head == false)
cam.transform.position = Vector3.Lerp(cam.transform.position, PosicMin, Time.deltaTime * Speed);
else {
cam.transform.position = Vector3.Lerp(cam.transform.position, PosicMax, Time.deltaTime * Speed);
}
if(head == false)
cam.transform.eulerAngles = Vector3.Lerp(cam.transform.rotation.eulerAngles, RotationMin, Time.deltaTime*Speed);
else {
cam.transform.eulerAngles = Vector3.Lerp(cam.transform.rotation.eulerAngles, RotationMax, Time.deltaTime*Speed);
}
Answer
You're using an exponential ease-out Lerp, which in real numbers never actually reaches completion. Each iteration, it moves a fraction of the remaining distance - always leaving a nonzero fraction left to go. Even in finite-precision floating point, it might not reach the destination value: at a certain point, the incremental displacement can round to less than the precision of the current value, resulting in no further change.
Fortunately, Unity's ==
comparison operator on Vector3s
and Quaternions
includes a tolerance range so it will return true
when they're almost the same.
The other issue that's going to throw you off is you're trying to interpolate Euler angles. This is almost always a bad idea. The game engine does not store or use Euler angles internally - it computes them on demand from the quaternion internals. That means the output you save in one frame might not match the input you get in the next frame, due to inevitable discontinuities in computing an Euler angle triplet from an orientation. That can be the source of the perpetual jitter in your implementation. And even without that complication, Euler angles do not interpolate well in general:
On the left: interpolating rotations with quaternions, we get smooth rotation along the shortest arc to the destination
On the right: interpolating rotations with Euler angles results in excessive spinning/tumbling
(See this UnityAnswers post for more details - unfortunately the original source of this animation is no longer available online nor in the Wayback machine, but you can play with an interactive app)
So, we can fix your code like so:
// Adjust for deltaTime correctly, given the non-linear nature of this use of Lerp.
float blend = 1.0f - Mathf.Pow(1.0f - Speed/30f, Time.deltaTime * 30f);
// Select destinations. This way we don't need to repeat our blend / check logic.
Vector3 destinationPosition = head ? PosicMax : PosicMin;
Quaternion destinationRotation = Quaternion.Euler(head ? RotationMax : RotationMin);
// Ease toward the selected destinations.
cam.transform.position = Vector3.Lerp(cam.transform.position, destinationPosition, blend);
cam.transform.rotation = Quaternion.Lerp(cam.transform.rotation, destinationRotation, blend);
// Check whether we're "close enough".
if(cam.transform.position == destinationPosition && cam.transform.rotation == destinationRotation) {
// Arrived!
}
If you want to more precisely control the threshold of what gets to count as "close enough," you can use Vector3.Distance
and Quaternion.Angle
to compute how far we are from our destinations, and compare those against custom thresholds.
No comments:
Post a Comment