- Home /
Using yield without StartCoroutine() in C#
Hi, I would like to have a function that do difference things each time I call it, like the following:
IEnumerator DoNextAction()
{
Debug.LogWarning("First");
yield return null;
Debug.LogWarning("Second");
yield return null;
Debug.LogWarning("Third");
yield return null;
Debug.LogWarning("Finish !");
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
DoNextAction();
}
}
I want that each time I click with my mouse, DoNextAction() is called and execute instructions until the yield return is called. That is normally how 'foreach iterators' work. (The first click should print "First", then if I click again "Second", etc...) The problem is that each time I click, DoNextAction does nothing.
And I don't want to use StartCoroutine(), because if I do:
void Update()
{
if (Input.GetMouseButtonDown(0))
{
StartCoroutine(DoNextAction());
}
}
StartCoroutine will do all the yields (each time click, it would print "First", "Second", "Third" and "Finish" all at once...)
What is the solution ?
Thanks.
Answer by TonyLi · Jun 05, 2013 at 07:55 PM
Try something like this:
IEnumerator<bool> actionEnumerator;
IEnumerable<bool> ActionIterator() {
Debug.LogWarning("First");
yield return true;
Debug.LogWarning("Second");
yield return true;
Debug.LogWarning("Third");
yield return true;
Debug.LogWarning("Finish !");
yield return false;
}
void Start() {
actionEnumerator = ActionIterator().GetEnumerator();
}
void Update() {
if (Input.GetMouseButtonDown(0)) {
actionEnumerator.MoveNext();
}
}
I just threw this into a project and confirmed that it works fine. You'll need to include these namespaces:
using UnityEngine;
using System.Collections.Generic;
Can someone tell me what the return true and return false do?
@almo: It does nothing in this case. I don't understand why he actually used a typed IEnumerator / IEnumerable. Since the yielded value is pointless here it would be much easier to just use IEnumerator. $$anonymous$$oveNext returns true if there is more code to go and naturally return false if the iteration is done.
Answer by Julianobsg · Jun 06, 2013 at 01:59 AM
First off all, you can´t... following unity reference:
When using JavaScript it is not necessary to use StartCoroutine, the compiler will do this for you. When writing C# code you must call StartCoroutine.
So to use yield you need a StartCoroutine, your actual problem is the idea of yield. The yield will continue in the next update, although the function is called or no.
What I suggest to do is not using yield, try to do a case function with a tick counter? Maybe every time you click it´s add a counter and for each click it does that function. That make more sense for me.
If you want to use yield anyway. You should know that wield wait for a function to complete, so for example, wait for seconds will expend X seconds to end, and the function will go after that ends.
Sorry about the english, or seemed rude, not my native language...
A coroutine is just a type of enumerator. You can use yield with any enumerator, not just coroutines.
that never been clear for me, and make sense, since the idea of using yield is to avoid status managing...
Answer by codestage · Aug 04, 2014 at 11:37 PM
Did you knew you may yield right from Unity's callbacks? Just like this:
private IEnumerator Start()
{
yield return new WaitForSeconds(5);
Debug.Log("Hey, 5 secs are passed by already!");
}
Same for Awake, Update and other callbacks AFAIR.
It is true that some callbacks can be coroutines, but especially Awake and Update can't. It's stated for each callback in the documentation which can and which can't be coroutines.
Also the OP don't wanted to use Unity's coroutine system at all but simply use an IEnumerator as normal iterator.