Weird problem with yields and WaitForSeconds

Hello everyone,

This is my first post so I’ll take the chance to introduce myself. My name is Pere and I am a programmer in a small indie game developer called StrangeLightGames. Pleased to meet you!

I’ve encountered a weird problem with yields. I’ve been able to fix it with a dirty trick, but I would like to know if someone has some experience with this issue or knows where the mistake might come from.

We are developing a 2.5 platformer with simple FSM and coroutines. Testing wall jumps we realized it sometimes responded in a different way when you tried to make a wall jump in the same wall. It works fine when the second wall jump makes contact on the wall below the first jump position. The problem comes after we execute a movement called “dash” before the first wall jump. In that case, the second wall jump makes contact on the wall a few points over the first wall jump location.

We use a simple swapping method for our states:

private void SwapHorizontal( StateHorizontal newState ) {
       switch( _currentHorizontal ) {
           // Finalitzem estats en cas de ser trencats de cop
       case StateHorizontal.Idle:
           break;
       case StateHorizontal.Inertia:
           break;
       case StateHorizontal.Run:
           break;
       case StateHorizontal.Crouch:
           IncreaseController();
           break;
       case StateHorizontal.Dash:
           StartCoroutine( ResetDash() );
           IncreaseController();
           break;
       case StateHorizontal.Slide:
           break;
       case StateHorizontal.TripOver:
           break;
       }

       switch( newState ) {
           // Inicialitzem el nou estat
       case StateHorizontal.Idle:
           StartCoroutine( "Idle" );
           break;
       case StateHorizontal.Inertia:
           StartCoroutine ( "Inertia" );
           break;
       case StateHorizontal.Run:
           StartCoroutine( "Run" );
           break;
       case StateHorizontal.Crouch:
           DecreaseController ();
           StartCoroutine ("Crouch");
           break;
       case StateHorizontal.Dash:
           StartCoroutine( "Dash" );
           break;
       case StateHorizontal.Slide:
           StopCoroutine(_currentHorizontal.ToString());
           StartCoroutine ("Slide");
           break;
       case StateHorizontal.TripOver:
           StopCoroutine(_currentHorizontal.ToString());
           StartCoroutine ("TripOver");
           break;
       }

       _currentHorizontal = newState;
   }

We then use coroutines for each state, Dash’s one is:

/**
    * Coroutina per al dash
    */
   private IEnumerator Dash() {
       DecreaseController();

       bool run = false;
       _canDash = false;
       movementProps.speed = MovementProperties.DASH_SPEED;
       Debug.Log ( "[MainCharControl::smile:ash] pre-yield 0.2f" );
       float time = Time.time;
       while ( time + 0.2f > Time.time ) {
           yield return null;
       }
       // yield return new WaitForSeconds( 0.2f );
       Debug.Log ( "[MainCharControl::smile:ash] post-yield 0.2f" );

       // Testegem si es pot aixecar
       RaycastHit hit;
       bool hitting; // Per saber si ens podem aixecar
       float marginTop = 0.3f; // Per saber si ens podem aixecar amb una mica de marge

       hitting = Physics.SphereCast( transform.position + _controller.center, _controller.height / 4, transform.up, out hit, _controller.height / 2 + marginTop );

       while( hitting ) {
           // Debug.Log ("[MainCharControl::smile:ash] Running");
           hitting = Physics.SphereCast(transform.position + _controller.center, _controller.height / 2, transform.up, out hit, _controller.height / 2 + marginTop );
           // jumpProperties.canJump = !hitting;
           yield return null;
       }

       run = ( _input.xAxis == movementProps.runDirection ); // Si no es la mateixa direccio, fem inertia

       StartCoroutine( ResetDash() );

       // Swap State
       if( run ) {
           SwapHorizontal( StateHorizontal.Run );
       } else {
           SwapHorizontal( StateHorizontal.Inertia );
       }
   }

I have realized the problem is a yield in the code yield return new WaitForSeconds( 0.2f );
Changing the code for:

while ( time + 0.2f > Time.time ) {
     yield return null;
}

the issue seems to disappear.

Anyone knows why this might be happening? Its not a big pain but it makes no sense to me and I would like to know if there is something I’m missing about WaitForSeconds().

Thank you all!

Curious. Probably won’t change anything, but you could try changing

StartCoroutine( “Dash” );

To:

StartCoroutine(Dash());

And make it Dash method public. I think I’ve run into problems before with private coroutines.

Hey SunnySunshine,

Tried both methods, and the behavior is the same :confused: