- Home /
Using a Coroutine to wait for user selection?
Hello my apologies if a similar question has been asked... I've tried searching but perhaps I'm not using the correct terms.
I am currently creating a turn-based board game. Each player has a certain amount of pieces on the board (think Final Fantasy Tactics), and each piece on the board can do multiple things (Move, Attack, Wait etc).
I'm currently having troubles figuring out a good way to set my code up so that when the user selects to "move" their board piece, I can highlight the moveable area... and then wait for the user to select one of the highlighted tiles.
I thought maybe a coroutine would work... but I can't seem to wrap my head around how to best pull it off.
Something along the lines of... (heavy pseudocode warning)...
void Move()
{
HighlightMoveableTiles();
yield return WaitForTileSelection();
MoveGamePieceToSelection();
}
Currently something along these lines is actually preventing the Move() method from firing at all..... yet when I comment out the yield return WaitForTileSelection() the method fires normally (but to completion).
I just want to ask... am I setting this up wrong? Can a coroutine not allow me to wait for a user to physically click something in the scene?
Thanks!
EDIT: Code added in case it helps, realize it is broken and does not work.
public override IEnumerator Use() { Debug.Log("Before coroutine"); //Highlight Selectable Tiles Movement mobileMovement = transform.root.GetComponent<Movement>(); HighlightTiles(mobileMovement); //Wait for selection yield return StartCoroutine(WaitForTileSelect()); Debug.Log("Selected a tile finally!"); //--If selection is valid, move to tile //--If selection is cancelled return to GUI base.Use(); //return null; }
List<GameObject> highlights = new List<GameObject>();
void HighlightTiles(Movement mobileMovement)
{
foreach (GameObject tile in mobileMovement.GetMoveableArea())
{
GameObject go = (GameObject)Instantiate(Resources.Load("Highlight"), tile.transform.position, Quaternion.identity);
InitHighlightComponent(go, tile);
highlights.Add(go);
}
}
void InitHighlightComponent(GameObject go, GameObject tile)
{
TileClickSelect component = go.GetComponent<TileClickSelect>();
if(component != null)
component.Tile = tile;
}
public void SelectTile(GameObject tile)
{
selectedTile = tile;
}
GameObject selectedTile;
IEnumerator WaitForTileSelect()
{
while (selectedTile == null)
{
yield return null;
}
}
Note: The Highlight code works as long as I remove the coroutine call, the only problem I'm having is that I cannot pause and wait for the user to select a tile for their piece to move to.
Proper question, good explanation, title, and caring about doubles. +1
Answer by Mike 3 · Jan 24, 2011 at 08:44 AM
I'm not sure how many issues in the code above are because of it being a snippet, but here goes:
1) Move (and WaitForTileSelection) has to be an IEnumerator return type if you want to use yield
2) You need to use yield return StartCoroutine(WaitForTileSelection()); for the yield line. Coroutines have to be called with StartCoroutine, or else you'll end up with none of the code being called at all.
3) You most likely need to call Move with StartCoroutine too
So in essence:
IEnumerator Move()
{
HighlightMoveableTiles();
yield return StartCoroutine(WaitForTileSelection());
MoveGamePieceToSelection();
}
Actually the code you put is what I really have. $$anonymous$$y snippet was meant only to serve as pseudocode as I'm not even really sure a coroutine is appropriate for what I want. I'll udpate my initial posting with the true code in case that helps, but I'm still struggling with the idea of the basic setup. The code itself atm does not work and is somewhat unimportant.
Answer by DavidB · Jan 24, 2011 at 04:03 PM
Urhg.... I have to stop trying to work coroutines late at night. I now have it working. Turns out I was just misunderstanding how a coroutine functions. I failed to call my IEnumerator Move()
function with a StartCoroutine(Move()) call. I was just calling it as "Move()". Apparently this matters doh!
Also I was misunderstanding that wherever your yield statements are... is the exact line that a coroutine will start back up at when it loops again. The lines above it will not be called! Therefore my while loop was not able to break I believe.
What you could do is put the while/wait loop from WaitForTileSelect into Use, and have the highlighting code inside of it so that it'll keep highlighting until you've selected the right one, at which point it'll continue the rest of the function
That would certainly work if I was just doing some temporary render effect, but I actually have a prefab'd game object that I just place in the scene to "highlight", so I only have to do it once.
Your answer
Follow this Question
Related Questions
Blocking and retrieving user keyboard input 0 Answers
Increment variable over time 4 Answers
Load skybox pics at startup w/o using all ram 1 Answer
problem with #pragma strict and Function type 1 Answer
Mathf.Clamp01 CoRoutine 1 Answer