- Home /
Help with the loop.
If I'm running this the _shouldchange bool will change like 5-10 seconds too late to false even if the Lerp is completed? how can I fix that?
public class ColorCycler : MonoBehaviour
{
public Color[] Colors;
public float Speed = 5;
int _currentIndex = 0;
Camera _cam;
public bool _shouldChange = false;
public float time;
public float CycleEverySeconds = 5f;
void Start()
{
_cam = GetComponent<Camera>();
_currentIndex = 0;
}
public void SetColor(Color color)
{
_cam.backgroundColor = color;
}
public void Cycle()
{
_shouldChange = true;
}
void Update()
{
time += Time.deltaTime;
if (time >= CycleEverySeconds)
{
Cycle();
time = 0;
}
if (_shouldChange == true)
{
var startColor = _cam.backgroundColor;
var endColor = Colors[0];
if (_currentIndex + 1 < Colors.Length)
{
endColor = Colors[_currentIndex + 1];
}
var newColor = Color.Lerp(startColor, endColor, Time.deltaTime * Speed);
SetColor(newColor);
if (newColor == endColor)
{
_shouldChange = false;
if (_currentIndex + 1 < Colors.Length)
{
_currentIndex++;
}
else
{
_currentIndex = 0;
}
}
}
}
}
Answer by FlaSh-G · Aug 19, 2020 at 06:46 PM
You're using lerp for a non-linear interpolation, which is not a bad thing to do, but you have to be aware what you're doing.
When you do
value = lerp(value, target, speed * deltaTime)
what you do is go x% of the way from "here" to "there" each update. So when speed * deltaTime
is, let's assume that for now, 0.5
, then you go 50% of the remaining way each time. If you have, say, 10 meters to go, you go 5 meters in the first update, 2.5 meters in the second, 1.25 meters, ...
This creates this neat "start fast, get slower" kind of interpolation, but it also means that, in a mathematical sense, you never reach your target, as you always ever decrease your distance by half.
In a more programming sense, you can actually reach the target as at some point, the difference between the value and its target becomes too small for the computer to represent with the amount of bits available for representing the numbers.
So, what you need to do: You either rework the way your tween works or you introduce an "epsilon" value - a small value that is considered a threshold for being finished. If the remaining distance between value and target is below that threshold, you consider the interpolation done.
Instead of
if (newColor == endColor)
you would write something like (but probably not exactly like)
if (((Vector4)newColor - (Vector4)endColor).magnitude < 0.05f)
Keep in mind that this kind of interpolation is anything but consistent when done in Update. Even with Time.deltaTime
applied in all the right places, you will get different durations for your animation with different FPS.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
c# wait script 2 Answers
Scale Object Using Lerp? 2 Answers
Aim down sights (HELP) 0 Answers