Hi, I’ve been trying to see how others have dealt with this topic, but I can’t get it working. I just want a light’s intensity to go from 0.0f to 0.46f smoothly over a period of 2 seconds.
If anyone can please offer any insight I would be grateful.
Its hand written but you get the point.
When something happens, change a bool to true, then if that bool is true, increment (or decrement) the intensity over time.
I’d probably use a tweening engine. We use LeanTween in a lot of projects at work, so using it for something like this is fairly easy to setup. There is also Dotween. Both have free versions that work really well.
+1 to this - I forgot about Mathf.MoveTowards, a nice and simple piece of code.
I would use yield return null instead though. Just because ive never seen yield return 0. Does that work?
For the sake of learning or to not bulk up the project I would say just write it yourself. Unless you want to do tons of ‘tweens’.
I have a question, what’s the math behind Time.deltaTime / nSeconds? Why the result yields the value it has to move in a frame? I tried to make sense of it (I like to learn why, instead of using something because it just works) but I couldn’t.
Ok, I think I get it. but I read here that the math behind MoveTowards is this:
public static float MoveTowards(float current, float target, float maxDelta)
{
if (Mathf.Abs(target - current) <= maxDelta)
{
return target;
}
return current + Mathf.Sign(target - current) * maxDelta;
}
so the third parameter in MoveTowards, maxDelta, is not the interpolation (as in Lerp) but the maximum change, and that’s why I don’t understand it well.
Sorry if I get some things mixed up! I really should start revisiting some math.
Aye, I stand corrected, I was wrong above. Deleted post to avoid misleading people.
The difference between Mathf.Lerp and Mathf.MoveTowards is that in MoveTowards, maxDelta is treated like the value to add to the current completion rather than the percentage of completion between the start and the finish values.
Time.DeltaTime / nSeconds is basically like saying you should add (time elapsed since the last frame / the amount of time we want the completion to take) to the current progress.
After nSeconds’s worth of Time.deltaTime has elapsed, we will arrive at a 1/1 ratio and the completion will be finished (if our target is 1).
void RaiseLightIntensity (float lightIntensity)
{
//Lets say the target intensity is 3
//Lets pretend we are running at a stable 60 fps
//Lets say we want to do this over 4 seconds
float target = 3f;
float nSeconds = 4f;
//In theory, time.deltaTime should always be around 0.016667f (1 second / 60 FPS)
//If we pass 0.0166667f (or Time.deltaTime) as a maxDelta value
//It will take 60 frames (60 x 0.0166667) to reach 1.
//Since we want to do it over 4 seconds (240 frames), we divide Time.deltaTime by 4.
//If we pass 0.0041667f (or Time.deltaTime / 4f) as a maxDelta value
//It will take 240 frames to reach 1.
//That'd be cool, IF we wanted to reach 1. Our target is 3.
//Since we don't want to reach 1, but actually 3, we have to multiply by target
//If we pass 0.0125f (Time.deltaTime / nSeconds * target) as the maxDelta value
//It will take 240 frames to reach our target (3), rather than the initial 1
float maxDelta = Time.deltaTime / nSeconds * target;
lightIntensity = MoveTowards (lightIntensity, target, maxDelta);
//lightIntensity will return 0.0125f after the first frame
//0.025f after the second, and this will go on until 3 is reached (240 frames)
}
Is this making anymore sense? Perhaps this is clearer?
The first one not quite! Since lerp returns a percentage of the distance between a and b, it will never reach b the way it’s setup, and will feel like it’s smoothing because the increment gained will be worth less and less every frames.
Here’s a post from Eric5h5 explaining why your current approach won’t work
Here’s a kickass article about lerping (Definitely a must-read in my opinion)
Here’s a different approach on how to lerp over a given amount of time.
Second one has a similar mistake as well. Since initial is incremented every frames, Mathf.Abs (target-initial) won’t remain “3” for the whole duration of the movement. It needs to remain 3 since that’s how it provides you with the correct constant increments.
I totally get it now, the article about lerp was really informative. And I don’t know why I didn’t see the mistake in the second one! I believe the lesson is “Always write the full code”