Search code examples
c#unity-game-enginelerp

Unity - Reversing Lerped Position Back to Original Position


My logic must be quite off here. Essentially, I have a loading bar, that when activated by a mouse hover, will have it's overlaying UI panel left position increase to give the loading effect. This works fine.

The problem is with reversing the UI panel left position back to its original posion (0,0) when its not activated in the second while loop. Here is my code -

IEnumerator LerpCoroutine()
{
    Vector2 xyz;

    float timeElapsed = 0;
    float lerpDuration = 2;

    Vector2 startPos = sliderOverlayRt.offsetMin;
    Vector2 x = new Vector2(0, 0);


    while (isActivated && timeElapsed < lerpDuration)
    {
        xyz = Vector2.Lerp(startPos, new Vector2(300, 0), EaseOut(timeElapsed / lerpDuration));
        sliderOverlayRt.offsetMin = xyz;
        timeElapsed += Time.deltaTime;
        yield return null;
    }
    while (!isActivated && timeElapsed < lerpDuration)
    {
        xyz = Vector2.Lerp(sliderOverlayRt.offsetMin, new Vector2(0, 0), EaseOut(timeElapsed / lerpDuration));
        sliderOverlayRt.offsetMin = xyz;
        timeElapsed += Time.deltaTime;
        yield return null;
    }
}

For some reason, sliderOverlayRt.offsetMin is set to zero in the second while loop, thus the UI panel left position shoots right back to (0,0).

If anyone could show a better way to do this, maybe without even having to use the double while statement, that would be hugely appreciated!

TLDR - I want to get the Vector2 to lerp from (0,0) -> (0,300) if isActivated. However, if !isActivated in the middle of the lerp transition, in which case it only went from (0,0) -> (0,150), then I want it to go from (0,150) -> (0,0).

Thanks.


Solution

  • Here's what I see:

    In the second loop, you're lerping from sliderOverlayRt.offsetMin back to (0,0), but you're immediately updating sliderOverlayRt.offsetMin right after that. So, on the next iteration, you're lerping from the updated sliderOverlayRt.offsetMin, but by a larger amount since the lerp factor is based on the time delta.

    Also, you're starting the second lerp at timeElapsed / lerpDuration. I imagine that you want the lerp factor to start at 0, not at some larger value.

    So, I'd try this.

    Also, I haven't tried to compile this.

    IEnumerator LerpCoroutine()
    {
        Vector2 xyz;
    
        float timeElapsed = 0;
        float lerpDuration = 2;
        float lerpFactor = 0; 
    
        Vector2 startPos = sliderOverlayRt.offsetMin;
        Vector2 x = new Vector2(0, 0);
        var lerpMax = new Vector3(300,0);
    
    
        while (isActivated && timeElapsed < lerpDuration)
        {
            xyz = Vector2.Lerp(startPos, lerpMax, EaseOut(lerpFactor / lerpDuration));
            sliderOverlayRt.offsetMin = xyz;
            timeElapsed += Time.deltaTime;
            /// increasing lerpFactor so the bar moves right...
            lerpFactor += time.deltaTime;
            yield return null;
        }
        while (!isActivated && lerpFactor >= 0)
        {
            xyz = Vector2.Lerp(startPos, lerpMax, EaseOut(lerpFactor / lerpDuration));
            sliderOverlayRt.offsetMin = xyz;
            timeElapsed += Time.deltaTime;
            /// decreasing lerpFactor here so the bar moves left
            lerpFactor -= Time.deltatime; 
            yield return null;
        }
    }
    

    TL;DR

    Keep your starting position on the second loop constant, make sure the lerp value makes sense, and you should be good.