I cant understand what is going on with this "yield" ......

first my code was like this:

function Lose(){
	yield WaitForSeconds(1.5);
	Time.timeScale = 0;
	guiMode = "Lose";
}

and i was calling it from another script. but it didnt work.
so i looked it up in the script reference,and i added this.

function Lose(){
	print(Time.deltaTime);
	yield WaitForSeconds(1.5);
	print(Time.deltaTime);
	Time.timeScale = 0;
	guiMode = "Lose";
}

this time only the first “print” was working, i never saw the second “print”.it was like the yied is forever,instead of 1.5 seconds.

then i changed it like this:

function Lose(){
	
	//yield WaitForSeconds(1.5);
	
	Time.timeScale = 0;
	guiMode = "Lose";
}

this time it worked immediatly

then i came up with this:

function Lose(){
	Wait();
}

function Wait(){
	
	yield WaitForSeconds(1.5);
	
	Time.timeScale = 0;
	guiMode = "Lose";
}

and then finally it worked.

but i just cant understand what’s going on …

i watch this unitycookie lunar lander tutorial in youtube, and followed it.but mine just worked out differently like this…

can somebody explain why??

I am no “pro” in UnityScript, but I have tried it myself and its works as acceptet. can you post all your code and dont forget the code from where you are calling your Lose function.

this is my full scripts:
1,the PlayerControl.js:(where i called my Lose() function).

var bottomThruster_R : ParticleSystem;
var bottomThruster_L : ParticleSystem;
var topThruster : ParticleSystem;
var leftThruster : ParticleSystem;
var rightThruster : ParticleSystem;

var explosion : ParticleSystem;

var hardness : int = 2;

var GUI : InGameGUI;

function Start () {
	GUI = GameObject.FindWithTag("GUI").GetComponent(InGameGUI);

}

function FixedUpdate () 
{
	if(Input.GetAxis("Horizontal") > 0)//checking for right arrow key
	{
		leftThruster.enableEmission = true;
		rigidbody.AddForce(10,0,0);
	}
	if(Input.GetAxis("Horizontal") < 0)//checking for left arrow key
	{
		rightThruster.enableEmission = true;
		rigidbody.AddForce(-10,0,0);
	}
	if(Input.GetAxis("Horizontal") == 0)//checking if no horizontal keys down
	{
		leftThruster.enableEmission = false;
		rightThruster.enableEmission = false;
	}
	
	if(Input.GetAxis("Vertical") > 0)//checking for up arrow key
	{
		bottomThruster_L.enableEmission = true;
		bottomThruster_R.enableEmission = true;
		rigidbody.AddForce(0,10,0);
	}
	if(Input.GetAxis("Vertical") < 0)//checking for Down arrow key
	{
		topThruster.enableEmission = true;
		rigidbody.AddForce(0,-10,0);
	}
	if(Input.GetAxis("Vertical") == 0)//checking if no vertical keys down
	{
		bottomThruster_L.enableEmission = false;
		bottomThruster_R.enableEmission = false;
		topThruster.enableEmission = false;
	}
}

function OnCollisionEnter (col : Collision) {
	if(col.relativeVelocity.magnitude >= hardness){
		
		Explode();
	}
	else if(col.gameObject.tag == "Platform"){
		Debug.Log("Platform hit!");
	}
}

function Explode(){
	GUI.Lose();
	Instantiate(explosion,transform.position,Quaternion.identity);
	Destroy(gameObject);
}

2,this is the InGameGUI script,where i have my Lose() function defined.

var guiMode : String = "InGame";
var numActivated : int;
var totalLZ : int;

function start (){
	
}

function Update(){

	if(Input.GetKeyDown("escape")){
		Time.timeScale = 0;
		guiMode = "Paused";
	}
	
}

function OnGUI(){
	if(guiMode == "Paused"){
		if(GUI.Button(Rect(Screen.width/2-75,Screen.height/2-20,150,30),"Resume Game")){
			Time.timeScale = 1;
			guiMode = "InGame";
			print("starting new game...");
		}
		if(GUI.Button(Rect(Screen.width/2-75,Screen.height/2+20,150,30),"Quit to Main Menu")){
			Time.timeScale = 1;
			print("continue game...");
			Application.LoadLevel(0);
		}
	}
	if(guiMode == "Win"){
		if(GUI.Button(Rect(Screen.width/2-75,Screen.height/2-20,150,30),"Next Level")){
			Time.timeScale = 1;
			guiMode = "InGame";
			Application.LoadLevel(Application.loadedLevel + 1);
			print("Next level");
		}
		if(GUI.Button(Rect(Screen.width/2-75,Screen.height/2+20,150,30),"Quit to Main Menu")){
			Time.timeScale = 1;
			print("quiting...");
			Application.LoadLevel(0);
		}
	}
	if(guiMode == "Lose"){
		if(GUI.Button(Rect(Screen.width/2-75,Screen.height/2-20,150,30),"Retry Level")){
			Time.timeScale = 1;
			guiMode = "InGame";
			Application.LoadLevel(Application.loadedLevel);
			print("Retry level");
		}
		if(GUI.Button(Rect(Screen.width/2-75,Screen.height/2+20,150,30),"Quit to Main Menu")){
			Time.timeScale = 1;
			print("quiting...");
			Application.LoadLevel(0);
		}
	}
}

function LZactivated(){
	numActivated++;
	if(numActivated == totalLZ){
		Win();
	}
}

function Win(){
	guiMode = "Win";
	Time.timeScale = 0;
	PlayerPrefs.SetInt("playerLevel",Application.loadedLevel+1);
}

function Lose(){
	Wait();
}

function Wait(){
	
	yield WaitForSeconds(1.5);
	Time.timeScale = 0;
	guiMode = "Lose";
}

Rename you GUI variable to something else. Lowercase for example. This might cause the problem

it’s not working… i have tried rename Lose(),but it just didnt work as long as i am calling it from my PlayerControl script.

i followed exactly from this tutorial:

in 33:40 ,you will see it.

I think the problem here maybe that you are calling yield from the event OnCollisionEnter instead of Update(). You also are not using it with the coroutine. I think the definition of “yield” is “wait for a next frame with an additional condition”. I’m maybe wrong here.

My suggestion is to try to define a boolean variable isLost in your PlayerControl module. Inside OnCollisionEnter set it to true. In your Update() method check if it is true then start a coroutine GUI.Lose. See if this works.

you’re calling the coroutine from an object you then destroy in the same frame… the next frame the coroutine doesn’t exist since it was connected to a gameobject that no longer exists.

if you call the coroutine from a function in the GUI script (OP last code block) the object the GUIscript is attached to still exists in subsequent frames to carry on processing the yield instruction.

At least that’s what it looks like to me :wink: it’s backend processing voodoo if not :stuck_out_tongue:

I think the idea here is that because YKpro is calling yield he doesn’t expect the Destroy to get called till 1.5 seconds later. But LeftyRighty is probably right (love the handle by the way :slight_smile: ) because what gets yielded is the Wait() and nothing else.

i tried this:

function Explode(){
	Gui.Lose();
	Instantiate(explosion,transform.position,Quaternion.identity);
	yield WaitForSeconds(2);
	Destroy(gameObject);
}

by adding another “yield WaitForSeconds(2);” i then let the player to destroy himself after 2 seconds the "Gui.Lose()"function is called.
since the “Lose()” function is like this:

function Lose(){
	//Wait();
	yield WaitForSeconds(1.5);
	Time.timeScale = 0;
	guiMode = "Lose";
}

so there is 0.5 seconds ahead of the destroy. so it worked!

I think LeftyRighty is right.:smile:

but did you guys watch the tutorial i paste there? somehow the scripts in the tutorial doesnt work like this.it still work even the player is destroyed.