Cannot get into method

Okay, when I go into debug and do a step-by-step in monodevelop I am able to see the line that says “EnterState_PlayerSelectingTarget()”, and then the yellow highlighter illuminates the first line of the method (private IEnumerator, etc…)

However, the method appears to be skipped after that: I never get the Debug message or any of the other code…

Does anyone why I can never execute the code in this method?

private IEnumerator EnterState_PlayerSelectingTarget() {
	Debug.Log ("EnterState_PlayerSelectingTarget");
	this.state = GamemasterStates.PlayerSelectingTarget;
	setCursorEnabled(true);
		
	targetHex = null;
		
	//Wait for the player to select a target hex
      	while(targetHex == null)
      	{
           yield return new WaitForSeconds(1);
      	}
		
	//Show the player where they are allowed to move
	reachableAreaScript.UpdateReachableHexes(activeModelScript.CurrentHex, activeModelScript.MovementPoints);
	reachableAreaScript.DisplayReachableHexes();
	//targetHex = hexGridScript.GetHexByIndex(3,3);
	EnterState_EngineMovingModel();
		
}

This is an IEnumerator that you’re trying to call. To execute it, you need to use StartCoroutine :slight_smile: - Like StartCoroutine(EnterState_PlayerSelectingTarget());

And, not that it’s related, but using methods like EnterState_PlayerSelectingTarget isn’t really elegant. - What would be nicer is that if you used an enum to represent your states, and then have one method EnterState(State state) that acts accordingly upon the argument state.

And don’t forget that there is more than one stepping method in debugging, there is step in, step out and step over - If you’re stepping over your method, you will never get inside it, so you need to step in :slight_smile: - More on debugging with monodev.

EDIT: About your waiting mechanism, I used to actually fall for this myself :slight_smile:
Here’s what you’re doing:

// some code
StartCoroutine(WaitForPlayer());
// some other code (which you intend for it to be executed AFTER you've waited for the player)

Where, WaitForPlayer:

IEnumerator WaitForPlayer()
{
   while (targetHex == null)
     yield return null;
}

To understand the problem, you have to understand how yield return works - yield return null; means skip what’s after the yield to the next frame and RESUME what’s after the Coroutine - it does NOT mean skip what’s after the yield AND what’s after the Coroutine to the next frame - yield return new WaitForSeconds(1); means, wait 1 second, and then execute what’s after the yield. In your case, there is ‘nothing’ after yield return null - so even if targetHex were to to assigned (not null), there’s nothing that you’re doing after the yield inside your Coroutine :slight_smile:

Here’s how execution will flow:

1 ->   // some code
2 ->   StartCoroutine(WaitForPlayer()); 
3 ->         while (targetHex == null)
4 ->             yield return null;
5 ->   // some other code (which you intend for it to be executed AFTER you've waited for the 

To fix this, there’s a couple ways:

1- Don’t wait inside a Coroutine, wait like this:

// some code here
while (targetHex == null)
   yield return null;
// resume :)

2- Use a isPlayerReady (or something) flag and stick to your waiting idea of using a Coroutine, like this:

isPlayerReady = false;
// some code here
StartCoroutine(WaitForPlayer());

Where, WaitForPlayer:

IEnumerator WaitForPlayer
{
   while (targetHex == null)
      yield return null;
   isPlayerReady = true;
}

And then somewhere else, like in Update:

if (isPlayerReady)
{
   isPlayerReady = false;
   // resume :)
}

3- Better yet, use events :slight_smile: - Have an event like, OnPlayerReady that gets ‘fired’ when you’ve assigned/populated all your stuff and you’re ready to go - inside, put whatever code you want, and let whatever interested in that event ‘subscribe’ to it.
More about events could be found here, here, here and everywhere googling “C# events”. Events are very powerful and will make your coding a lot more pleasant!

There is not really a reason to necessarily try to set up an IEnumerator to check a condition. If you are just checking a condition you could easily have something like:

bool targetHexBool;
bool moveActiveBool;

float timer;

void Start()
{
targetHexBool = false;
moveActiveBool = false;

timer = 1;
}

void Update()
{

if (targetHex == null)
{
targetHexBool = false;
return;
}

else if ((targetHex != null) && (moveActiveBool == false))
{
targetHexBool = true;
moveActiveBool = true;
StartCoroutine(playerMoveFunction(timer));
}

}

IEnumerator playerMoveFunction(float timer)
	{
		yield return new WaitForSeconds(timer);
		//do all of your game logic you wanted a delay for
//may require calling another function, Coroutine, setting bools to control Update() conditions

//once your done with all the move stuff reset the bools and wait for the next PlayerMoveFunction
//may not necessarily be inside this Ienumerator
targetHex = null;
targetHexBool = false;
moveActiveBool = false;

	}

Impossible to know how much that will help you but just an example how to handle waiting for conditions before calling a function having a delay in the function, etc.

I’m not quite following what you are doing in the game though so this is kind of a general example of how one might accomplish this without using while() which kind of defeats the purpose of using an Ienumerator in my opinion.

Thanks for all your help vexe and RyanZimmerman, but I finally went with a workaround; I am just going to put more stuff in update instead.

Getting the coroutines working would have been more elegant though, maybe I’ll come back to it later.