2

I'm using Unity's animation curves which unfortunately only have an Evaluate function that given time gives the value. I want to create a method that does the opposite of that. value gives time. I looked at this post: Unity get time by value but all the answers refer to inverting the curve which I think, and most comments agree, is cumbersome and error prone. I figured a better solution would be to use binary search. However, my current implementation sometimes fails to find the time.

For context the curve represents the velocity of a car as it accelerates. It is always monotonic increasing. So far this is what I've got:

 float GetTimeOnCurve(AnimationCurve c, float speed)
    {
        if (speed < c.keys[0].value)
        {
            return c.keys[0].time;
        }else if (speed > c.keys.Last().value)
        {
            return c.keys.Last().time;
        }

        float min = c.keys[0].time;
        float max = c.keys.Last().time;
        const float elipson = 0.001f;
        while (min <= max)
        {
            float mid = (min + max) / 2;
            if (speed >= c.Evaluate(mid) - elipson && speed <= c.Evaluate(mid) + elipson)
            {
                return mid;
            }else if (speed < c.Evaluate(mid))
            {
                max = mid - elipson;
            }
            else
            {
                min = mid + elipson;
            }
        }
        Debug.LogError("Speed not found");
        return TopSpeed;
    }

What can I do so that the time is always found?

Jacob Edie
  • 69
  • 6
  • 1
    _"sometimes fails to find the time"._ How exactly does it fail? – Abhinav Mathur Mar 28 '22 at 05:22
  • What if a certain value is **never** covered by the animation curve? What if a certain value is covered **multiple** times in an animation curve? – derHugo Mar 28 '22 at 07:55
  • Besides that ... `and most comments agree, is cumbersome and error prone` .. there is exactly one commenter on the most upvoted answer ^^ For sure there might be some edge cases but honestly I think the inversion is the best you can get if you don't want a plot check like you are doing – derHugo Mar 28 '22 at 08:26

1 Answers1

1

steep curve

It may fail on a steep curve, you should change the condition to

speed >= c.Evaluate(mid - elipson) && speed <= c.Evaluate(mid + elipson)
shingo
  • 18,436
  • 5
  • 23
  • 42