Trying to get Lerp and Slerp to handle bringing the position and rotation of an object slowly back to it’s original saved position after being knocked… It’s not working.
Don’t put Time.deltaTime as the interpolation factor. I know that there’s a lot of people around saying that’s how to use them, but it’s bad advice from people who don’t actually understand what they’re talking about.
Time actually is a very misleading name for the lerp factor parameter in the lerp functions. Once I had to explain for 30 minutes that the “time” parameter can be called factor, lerp factor, percentage, banana. Anyhow, I’ll leave this for people who will understand it easier with math
time = clamp(time, 0, 1);
result = ((1 - time) * Input1) + (time * Input2);
Other way of saying, is that time is in lerp… uhm… space. So for example, instead of using time, you’ll actually use (currentLerpTimeElapsed / totalLerpDuration) as your ‘time’.
That’s a really good point, calling it “time” is pretty confusing. At the very least it should be considered as a noralized time, because that’s something that people can grasp pretty easily.
I usually just explain the lerp parameter as a percentage. Given a t from 0 to 1, you’ll get a result that is t percent between a and b.
If you want a value that changes over time, t needs to change over time.
Like so:
public float min = 0f;
public float max = 100f;
public float lerpTime = 1f;
float currentLerpTime = lerpTime + 1f;
public void StartLerping() {
currentLerpTime = 0f;
}
void Start() {
StartLerping();
}
void Update() {
currentLerpTime += Time.deltaTime;
if (currentLerpTime <= lerpTime) {
float perc = currentLerpTime / lerpTime;
float current = Mathf.Lerp(min, max, perc);
Debug.Log("current: " + current);
} else {
Debug.Log("finished");
}
}
You could just as easily vary t by any other parameter, though. What if you want some light’s brightness to lerp as it moves? You could vary t based on its position along the world’s x-axis, either as a range between two values or as a sine wave as it travels.
Thanks for all your replies. I’ve now listened to everything you’ve said and tried re-doing my mode. The position one works perfectly. I have an issue with my rotation one however. Let me show you.
public class PlayerScript : MonoBehaviour {
int playerHealth = 100;
float moonTapped, reposStart, furthestDist, furthestRot, reposSpeed = 2;
Vector3 savedPos, savedRot;
// Use this for initialization
void Start ()
{
// Setting the Civilisation's original position.
savedPos = transform.position;
savedRot = transform.eulerAngles;
}
// Passed health lost from the magnitude of the velocity from the moon
playerHealth -= healthLost;
// gives a delay before re-aligning the civilisation's position, and sets the start time for reposition as well.
reposStart = Time.time;
moonTapped = 1.2f;
// This puts the civilisation's back in their nuetral position after being hit..
void FixedUpdate()
{
// Gives the Civilsations a delay before they reposition
if(moonTapped > 0)
{
// If timer's still higher than requirement, minus time from it.
moonTapped -= Time.deltaTime;
// Gets the furthest distance/rotation travelled before the delay expires.
furthestDist = Vector3.Distance(savedPos, transform.position);
furthestRot = Vector3.Dot(savedRot, transform.eulerAngles);
// Don't let it recalibrate if not ready. Return that shit.
return;
}
// Takes the time travelled divided by the total journey left, to get the fraction of the journey travelled.
float timePosCovered = (Time.time - reposStart) * reposSpeed;
float timeRotCovered = (Time.time - reposStart) * (reposSpeed + 5);
float fractureDistJourney = timePosCovered / furthestDist;
float fractureRotJourney = timeRotCovered / furthestRot;
// Repositions the well.. position.
if(savedPos != transform.position)
{
Vector3 currPos = transform.position;
transform.position = Vector3.Lerp(currPos, savedPos, fractureDistJourney);
}
// Repositions the rotation.
if(savedRot != transform.eulerAngles)
{
Vector3 newRot = Vector3.Slerp(transform.eulerAngles, savedRot, fractureRotJourney);
Quaternion rotation = Quaternion.Euler(newRot);
transform.rotation = rotation;
}
}
The rotation does a ‘full circle’ when hit… and doesn’t go to it’s original rotation by the quickest route. Sometimes spinning three times.