0
\$\begingroup\$

For the sake of learning about coroutine, I want to convert the following to a cleaner Update that just calls a coroutine. How would I do that?

using UnityEngine;

public class Controller : MonoBehaviour
{
    public float speed = 5f;
    private float deltaX;

    void Start()
    {
        deltaX = transform.localEulerAngles.x;
    }
    void Update()
    {
        deltaX += Input.GetAxis("Vertical") * speed;
        deltaX = Mathf.Clamp(deltaX, -90f, 90f);
        transform.localEulerAngles = new Vector3(deltaX, transform.localEulerAngles.y, transform.localEulerAngles.z);
    }
}
\$\endgroup\$
3
\$\begingroup\$

If each call to Update calls a coroutine, then you are creating a new coroutine each update and each coroutine will run in parallel with those created before. Your object will rotate faster and faster, while your framerate will get lower and lower due to the huge number of coroutines executed in parallel. That's unlikely to be what you want. If you want to run a coroutine, you generally only create that coroutine once.

So if your intention is to put the rotation code into a separate method so your Update function is "cleaner", then you would usually do that by creating a private method in the class and calling it as a regular method call:

using UnityEngine;

public class Controller : MonoBehaviour
{
    public float speed = 5f;
    private float deltaX;

    void Start()
    {
        deltaX = transform.localEulerAngles.x;
    }

    void Update()
    {
        UpdateRotation();
    }

    private void UpdateRotation()
    {
        deltaX += Input.GetAxis("Vertical") * speed;
        deltaX = Mathf.Clamp(deltaX, -90f, 90f);
        transform.localEulerAngles = new Vector3(deltaX, transform.localEulerAngles.y, transform.localEulerAngles.z);
    }
}

If you really want to do this with a coroutine (although I see no good reason here why you should), then you would want to start that coroutine from the Start method so it only gets created once:

using UnityEngine;

public class Controller : MonoBehaviour
{
    public float speed = 5f;
    private float deltaX;

    void Start()
    {
        deltaX = transform.localEulerAngles.x;
        StartCoroutine(UpdateRotationCoroutine());
    }


    private IEnumerator UpdateRotationCoroutine()
    {
        while(true) { // coroutine runs forever
            deltaX += Input.GetAxis("Vertical") * speed;
            deltaX = Mathf.Clamp(deltaX, -90f, 90f);
            transform.localEulerAngles = new Vector3(deltaX, transform.localEulerAngles.y, transform.localEulerAngles.z);
            yield return new WaitForFixedUpdate();
        }
    }
}

Here is an example of a more useful application of coroutines - one where a coroutine is started when the user presses the F key and that coroutine runs for 100 fixed updates. The player is able to start multiple coroutines in parallel by mashing the F key which will result in a faster rotation:

using UnityEngine;

public class Controller : MonoBehaviour
{
    public float speed = 90f;

    void Update() {
        if (Input.GetKeyDown(KeyCode.F)) {
             StartCoroutine(UpdateRotationCoroutine());
        }
    }

    private IEnumerator UpdateRotationCoroutine()
    {
        for (int i = 0; i < 100; i++) { // coroutine runs for 100 updates
            transform.Rotate(speed * Time.fixedDeltaTime, 0.0f, 0.0f);
            yield return new WaitForFixedUpdate();
        }
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ By the way, Start itself can be a coroutine \$\endgroup\$ – trollingchar Jul 17 at 14:27
  • \$\begingroup\$ Is it always a good idea to multiply the Input.GetAxis by Time.deltaTime to mitigate frame rate related issue? \$\endgroup\$ – Money Oriented Programmer Jul 17 at 14:47
  • 1
    \$\begingroup\$ @GoldDiggingProgrammer Yes, it is. If you don't, then players with higher framerates can move faster. Unless you are using FixedUpdate instead of Update, then you should use Time.fixedDeltaTime. But that's a different question. \$\endgroup\$ – Philipp Jul 17 at 14:49
  • \$\begingroup\$ OK. Thank you...! \$\endgroup\$ – Money Oriented Programmer Jul 17 at 14:50
  • 1
    \$\begingroup\$ Provided that axis is an analog stick value, not a mouse delta position (which is already smaller at higher framerates) \$\endgroup\$ – DMGregory Jul 17 at 16:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.