For loop in Coroutine isn't working.

I’m trying to move the camera up when a GUI element comes on screen and back down when it goes away. There’s supposed to be a transition where the Camera moves up at a certain speed instead of teleporting, but it’s not working. I found out that when the Coroutine is called, it skips over the for loop.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraController : MonoBehaviour
{
    public float defaultHeight = 16f;
    public float onGUIHeight = 13f;
    public float transitionTime = 1f;
    public float subPositions = 10f;

    bool onGUI = false;

    int i = 0;

    void Start()
    {
        // Sets the position to the default value.
        transform.position = new Vector3(transform.position.x, defaultHeight, transform.position.z);
    }
  
    void Update()
    {
        if (Input.GetKeyDown("space"))
        {
            if (onGUI == true)
            {
                onGUI = false;
                StartCoroutine(ExitGUI());
            } else if (onGUI == false)
            {
                onGUI = true;
                StartCoroutine(EnterGUI());
            }
        }
    }

    public IEnumerator EnterGUI()
    {
        for (i = 0; i > subPositions; i++)
        {
            transform.position = new Vector3(transform.position.x, onGUIHeight * ((i + 1) / subPositions), transform.position.z);
            yield return new WaitForSeconds(transitionTime / subPositions);
        }

        transform.position = new Vector3(transform.position.x, onGUIHeight, transform.position.z);
    }

    public IEnumerator ExitGUI()
    {
        for (i = 0; i > subPositions; i++)
        {
            transform.position = new Vector3(transform.position.x, defaultHeight * ((subPositions - i) / subPositions), transform.position.z);
            yield return new WaitForSeconds(transitionTime / subPositions);
        }

        transform.position = new Vector3(transform.position.x, defaultHeight, transform.position.z);
    }
}

The camera teleports to the location instead of moving at a constant speed. I’m not sure why this happens or what I can do about it. Thanks for your help in advance :slight_smile:

The issue is your for loop.
Since you are doing i++, but you are checking if i > subPositions, but you’re starting at 0.

It should be i < subPositions

Remember the second part of a for loop is similar to a while statement. So you’re essentially telling it, while i > subPositions, do the code inside. Which it is never true.

1 Like

Ohhhhhhh… thanks a lot! I thought that it only exited the loop if the condition was met not stayed inside.

It may also be worth noting that you could get a smoother motion if you updated every frame, rather than using a fixed number of subPositions. That might look something like:

    public IEnumerator EnterGUI()
    {
        float timeSoFar = 0;
        while (timeSoFar < transitionTime)
        {
            float desiredHeight = Mathf.Lerp(defaultHeight, onGUIHeight, timeSoFar / transitionTime);
            transform.position = new Vector3(transform.position.x, desiredHeight, transform.position.z);
            yield return null;  // waits until the next frame, however long that is
            timeSoFar += Time.deltaTime;
        }
        transform.position = new Vector3(transform.position.x, onGUIHeight, transform.position.z);
    }

Of course, if you are intentionally making it less smooth (e.g. to simulate a machine with a ratchet or something), then you can ignore this.

1 Like