- Home /
Using coroutine as Update(). Waiting until the button is pressed.
I am making a choice-based text adventure. There are 3 types of blocks, that are spawned on the screen: Speech (text), Choice (maybe set variables), Fork (check variables). So it's a tree structure - each one has a final exit. Choice and Fork have multiple exit options, and the final one should be evaluated. CurrentBlock goes through this scenario (all code is semi-pseudo or simplified):
Display()
EvaluateExit()
(Setting NextBlock. if Speech - chose the only one, if Choice - options buttons are spawned, on click we pass its exit, if Fork - check variables and conditions)Next() { CurrentBlock = NextBlock; NextBlock = null; Loop(CurrentBlock); }
Well, this is a Loop method for a Choice block.
public void LoopChoice(Choice choice) { Debug.Log("Current is choice!"); Display(choice); StartCoroutine(EvaluateExit(choice)); Next(); }
My question is how to make it wait until I press the button and only then go to Next()? I tried making the Choice's "EvaluateExit()" a coroutine, as you can see above. In the loop method I started it. I needed this coroutine to work as Update() method, so I made a while loop.
private IEnumerator EvaluateExit(Choice c) { print("Evaluating choice exit... Waiting for choice to be made..."); while (!choiceMade) { yield return null; } // set the evaluated exit to NextBlock print("Choice exit evaluated."); }
where choiceMade
is set by an event, that is triggered, when the button is clicked. I am going to pass the exit block as an EventArgs and set NextBlock
to it afterwards.
The problem is I don's really get the coroutines, but I found online, that yield return null
would help the loop last forever while the condition is true. So when I click the button it should stop, and the scenario should continue and Next()
should begin. But as I found out debugging, once it gets yield return null
, it skips all the coroutine, executes Next()
, and only after this it goes back to the coroutine and loops until I click the button. After I click the button happens nothing, when Next()
should.
I know it's hard to understand all of this code and what I am trying to do. But if you do, I'll provide you more code or any answer, if you just help me figure this out.
One thing: I'm trying not to use Update()
in this game at all.
Answer by SirPaddow · Jun 04, 2019 at 05:40 PM
It is the purpose of the coroutines to play asynchronously, so it sounds normal that the "Next()" and coroutine processes are played (virtually) simultenaously.
If Next() needs to be called at the end of the coroutine, you can move it to the end of your coroutine's content, something like this:
public class MyGame : MonoBehaviour
{
public bool choiceMade = false;
public void Start()
{
Next();
}
private void Next()
{
// Go to next block
bool requireUserInteraction = true; // check if it's a choice
Loop(/* your current block*/ null, requireUserInteraction);
}
private void Loop(object currentBlock, bool requireUserInteraction)
{
// Display(currentBlock);
if (requireUserInteraction)
{
StartCoroutine(ContinueOnUserInteraction(currentBlock));
}
else
{
Next();
}
}
private IEnumerator ContinueOnUserInteraction(object currentBlock)
{
choiceMade = false;
while (!choiceMade)
{
yield return null;
}
Next();
}
}
Thanks for the answer! I already figured out I had to put "Next()" at the end of the coroutine, but how to make my code more pretty? Because if so, I should rename "EvaluateExit()" to "EvaluateExitAndNext()" for the sake of consistency. Your code makes much sence though, I'll try to use it somehow.
Okay, I think I just now realised how dumb my question was and how simple this is! Thanks again.