Relu
Relu

Reputation: 37

Why Are My Image Positions Lerping At Two Different Speeds?

I've got some simple code here. The issue I am having is that the images contract to the center (local position Vector3.zero) at what seems to be nearly double the speed as they move away from the center. I believe I am using them same logic to move them so I was wondering if anyone could tell me what could cause such behavior.

Any advice on making the code itself better is also welcome but my main concern is the speed of the interpolation. I probably should have passed the current time via parameter instead of the total time but you know... I do not make perfect decisions the first time every time.

The specific lines in questions:

IEnumerator ContractImages(float totalTime)
{
    yield return m_WaitForEndOfFrame;

    m_CurrentContractionTime += Time.deltaTime;

    float t =  m_CurrentContractionTime / totalTime;

    Debug.Log(string.Format("Expansion Rate Factor: {0}", t));
    Debug.Log(string.Format("Current Expansion Time: {0}", m_CurrentContractionTime));

    for (int i = 0; i < m_MovingImages.Length; i++)
    {
        var r = m_MovingImages[i].GetComponent<RectTransform>(); //Optimize

        r.localPosition = Vector3.Lerp(r.localPosition, Vector3.zero, t);
    }

    if (m_CurrentContractionTime < totalTime)
        m_ContractionRoutine = StartCoroutine(ContractImages(totalTime));

    else if (m_ContractionRoutine != null)
    {
        StopCoroutine(m_ContractionRoutine);
        InvokeContractionComplete();
        m_CurrentContractionTime = 0;
    }
}

IEnumerator ExpandImages(float totalTime)
{
    yield return m_WaitForEndOfFrame;

    m_CurrentExpansionTime += Time.deltaTime;

    float t = m_CurrentExpansionTime / totalTime;

    Debug.Log(string.Format("Expansion Rate Factor: {0}", t));
    Debug.Log(string.Format("Current Expansion Time: {0}", m_CurrentExpansionTime));

    for (int i = 0; i < m_MovingImages.Length; i++)
    {
        var r = m_MovingImages[i].GetComponent<RectTransform>(); //Optimize

        r.localPosition = Vector3.Lerp(Vector3.zero, m_StartingVectors[i], t);
    }

    if (m_CurrentExpansionTime < totalTime)
        m_ContractionRoutine = StartCoroutine(ExpandImages(totalTime));

    else if (m_ContractionRoutine != null)
    {
        StopCoroutine(m_ExpansionRoutine);
        InvokeExpansionComplete();

        Debug.Log("Expansion Complete: " + totalTime / m_CurrentExpansionTime);
        m_CurrentExpansionTime = 0;
    }
}

Upvotes: 0

Views: 35

Answers (1)

Ruzihm
Ruzihm

Reputation: 20259

Well the first difference that seems obvious is that in ContractImages, you lerp from the current position, which grows ever closer to the destination, and in ExpandImages, you lerp from a constant position. So of course the ContractImages lerp will progress faster in the middle of the lerp.

For instance, assuming the expand position is new Vector3(1f,0f,0f) and totalTime is 1f, and Time.deltaTime is 0.1f:

First frame

Contract

r.localPosition = Vector3.Lerp(new Vector3(1f,0f,0f), Vector3.zero, 0.1f); 
             // = new Vector3(0.9f, 0f, 0f); 
             // dist = 0.1f

Expand

r.localPosition = Vector3.Lerp(Vector3.zero, new Vector3(1f,0f,0f), 0.1f);
             // = new Vector3(0.1f, 0f, 0f);
             // dist = 0.1f

Second frame

Contract

r.localPosition = Vector3.Lerp(new Vector3(0.9f,0f,0f), Vector3.zero, 0.2f); 
             // = new Vector3(0.78f, 0f, 0f);
             // dist = 0.22f

Expand

r.localPosition = Vector3.Lerp(Vector3.zero, new Vector3(1f,0f,0f), 0.2f);
             // = new Vector3(0.2f, 0f, 0f);
             // dist = 0.2f

Third frame

Contract

r.localPosition = Vector3.Lerp(new Vector3(0.78f,0f,0f), Vector3.zero, 0.3f); 
             // = new Vector3(0.546f, 0f, 0f);
             // dist = 0.454f

Expand

r.localPosition = Vector3.Lerp(Vector3.zero, new Vector3(1f,0f,0f), 0.3f);
             // = new Vector3(0.3f, 0f, 0f);
             // dist = 0.3f

Basically, you should consider lerping between constants in both cases:

IEnumerator ContractImages(float totalTime)
{
    yield return m_WaitForEndOfFrame;

    m_CurrentContractionTime += Time.deltaTime;

    float t =  m_CurrentContractionTime / totalTime;

    Debug.Log(string.Format("Expansion Rate Factor: {0}", t));
    Debug.Log(string.Format("Current Expansion Time: {0}", m_CurrentContractionTime));

    for (int i = 0; i < m_MovingImages.Length; i++)
    {
        var r = m_MovingImages[i].GetComponent<RectTransform>(); //Optimize

        r.localPosition = Vector3.Lerp(m_StartingVectors[i], Vector3.zero, t);
    }

    if (m_CurrentContractionTime < totalTime)
        m_ContractionRoutine = StartCoroutine(ContractImages(totalTime));

    else if (m_ContractionRoutine != null)
    {
        StopCoroutine(m_ContractionRoutine);
        InvokeContractionComplete();
        m_CurrentContractionTime = 0;
    }
}

Upvotes: 1

Related Questions