Why is StartCoroutine being ignored?

I created a door script. It’s supposed to open the door, wait five seconds and then close. The opening and closing is done with animations.

Here’s the problematic part of the code:

	IEnumerator DoorTime()
	{
		Time.timeScale = 1;
		yield return new WaitForSeconds (DoorTimer);
	}

	void changeDoorState()
	{

			theDoor.animation.CrossFade("Open");
			//theDoor.audio.PlayOneShot();
			doorIsClosed = false;

		StartCoroutine(DoorTime());

			theDoor.animation.CrossFade("Close");
			//theDoor.audio.PlayOneShot();
			doorIsClosed = true;

	}

and here’s the full code:

using UnityEngine;
using System.Collections;

public class DoorLogic : MonoBehaviour {
	
	public Transform theDoor;
	public GameObject DoorSideA;
	public GameObject DoorSideB;
	public GameObject RoomA;
	public GameObject RoomB;
	static float DoorTimer = 5.0f;
	private bool doorIsClosed = true;
	private bool drawGUI = false;

	void OnTriggerEnter(Collider theCollider)
		{
			if(theCollider.tag == "Player")
			{
				drawGUI = true;
			}
		}
	
	void OnTriggerExit(Collider theCollider)
		{
			if(theCollider.tag == "Player")
			{
				drawGUI = false;
			}
		}
	
	void OnGUI()
	{
		if (drawGUI == true)
		{
			GUI.Box( new Rect(Screen.width/2-51,200,102,22),"Press 'E' to Open");
		}
	}
	
	// Update is called once per frame
	void Update () 
	{
	 if (drawGUI == true && Input.GetKeyDown( KeyCode.E))
		{
			changeDoorState();
		}
	}

	IEnumerator DoorTime()
	{
		Time.timeScale = 1;
		yield return new WaitForSeconds (DoorTimer);
	}

	void changeDoorState()
	{

			theDoor.animation.CrossFade("Open");
			//theDoor.audio.PlayOneShot();
			doorIsClosed = false;

		StartCoroutine(DoorTime());

			theDoor.animation.CrossFade("Close");
			//theDoor.audio.PlayOneShot();
			doorIsClosed = true;

	}

}

please help

2 Answers

2

When you hit the yield on line 51 of the second script DoorTime() returns immediately. One way to fix your code, is to make ‘changeDoorState’ your coroutine:

IEnumerator changeDoorState()
    {
 
         theDoor.animation.CrossFade("Open");
         //theDoor.audio.PlayOneShot();
         doorIsClosed = false;
 
         Time.timeScale = 1;
         yield return new WaitForSeconds (DoorTimer);
 
         theDoor.animation.CrossFade("Close");
         //theDoor.audio.PlayOneShot();
         doorIsClosed = true;
    }

Then on line 44 you would start the coroutine rather than calling the function.

Also, because the animation time of the door is playing while you're counting down, you're not getting a full 5 seconds (or whatever DoorTimer is set to). You may consider adding this line of code after setting doorIsClosed to false (line 7 in code above at time of post): while (theDoor.animation.isPlaying) yield return null; This will ensure that your door is fully open for the amount of time that you intend, regardless of animation changes (lengthening or shortening of animation duration by an artist).

thank you, that solved the problem, I'll refer to the answers more often

When you yield from the co-routine, processing carries right on on the next line (After the StartCoroutine call). Only the code after the yield, within the coroutine itself waits for the timeout.

Move

 theDoor.animation.CrossFade("Close");
//theDoor.audio.PlayOneShot();
doorIsClosed = true;

inside the co-routine, placing it after the yield.