Search Unity

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

Discussion in 'Scripting' started by YKpro, May 14, 2013.

  1. YKpro

    YKpro

    Joined:
    May 14, 2013
    Posts:
    12
    first my code was like this:

    Code (csharp):
    1. function Lose(){
    2.     yield WaitForSeconds(1.5);
    3.     Time.timeScale = 0;
    4.     guiMode = "Lose";
    5. }
    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.

    Code (csharp):
    1. function Lose(){
    2.     print(Time.deltaTime);
    3.     yield WaitForSeconds(1.5);
    4.     print(Time.deltaTime);
    5.     Time.timeScale = 0;
    6.     guiMode = "Lose";
    7. }
    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:


    Code (csharp):
    1. function Lose(){
    2.    
    3.     //yield WaitForSeconds(1.5);
    4.    
    5.     Time.timeScale = 0;
    6.     guiMode = "Lose";
    7. }
    this time it worked immediatly

    then i came up with this:


    Code (csharp):
    1. function Lose(){
    2.     Wait();
    3. }
    4.  
    5. function Wait(){
    6.    
    7.     yield WaitForSeconds(1.5);
    8.    
    9.     Time.timeScale = 0;
    10.     guiMode = "Lose";
    11. }
    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??
     
  2. Deleted User

    Deleted User

    Guest

    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.
     
  3. YKpro

    YKpro

    Joined:
    May 14, 2013
    Posts:
    12
    this is my full scripts:
    1,the PlayerControl.js:(where i called my Lose() function).

    Code (csharp):
    1. var bottomThruster_R : ParticleSystem;
    2. var bottomThruster_L : ParticleSystem;
    3. var topThruster : ParticleSystem;
    4. var leftThruster : ParticleSystem;
    5. var rightThruster : ParticleSystem;
    6.  
    7. var explosion : ParticleSystem;
    8.  
    9. var hardness : int = 2;
    10.  
    11. var GUI : InGameGUI;
    12.  
    13. function Start () {
    14.     GUI = GameObject.FindWithTag("GUI").GetComponent(InGameGUI);
    15.  
    16. }
    17.  
    18. function FixedUpdate ()
    19. {
    20.     if(Input.GetAxis("Horizontal") > 0)//checking for right arrow key
    21.     {
    22.         leftThruster.enableEmission = true;
    23.         rigidbody.AddForce(10,0,0);
    24.     }
    25.     if(Input.GetAxis("Horizontal") < 0)//checking for left arrow key
    26.     {
    27.         rightThruster.enableEmission = true;
    28.         rigidbody.AddForce(-10,0,0);
    29.     }
    30.     if(Input.GetAxis("Horizontal") == 0)//checking if no horizontal keys down
    31.     {
    32.         leftThruster.enableEmission = false;
    33.         rightThruster.enableEmission = false;
    34.     }
    35.    
    36.     if(Input.GetAxis("Vertical") > 0)//checking for up arrow key
    37.     {
    38.         bottomThruster_L.enableEmission = true;
    39.         bottomThruster_R.enableEmission = true;
    40.         rigidbody.AddForce(0,10,0);
    41.     }
    42.     if(Input.GetAxis("Vertical") < 0)//checking for Down arrow key
    43.     {
    44.         topThruster.enableEmission = true;
    45.         rigidbody.AddForce(0,-10,0);
    46.     }
    47.     if(Input.GetAxis("Vertical") == 0)//checking if no vertical keys down
    48.     {
    49.         bottomThruster_L.enableEmission = false;
    50.         bottomThruster_R.enableEmission = false;
    51.         topThruster.enableEmission = false;
    52.     }
    53. }
    54.  
    55. function OnCollisionEnter (col : Collision) {
    56.     if(col.relativeVelocity.magnitude >= hardness){
    57.        
    58.         Explode();
    59.     }
    60.     else if(col.gameObject.tag == "Platform"){
    61.         Debug.Log("Platform hit!");
    62.     }
    63. }
    64.  
    65. function Explode(){
    66.     GUI.Lose();
    67.     Instantiate(explosion,transform.position,Quaternion.identity);
    68.     Destroy(gameObject);
    69. }
    2,this is the InGameGUI script,where i have my Lose() function defined.

    Code (csharp):
    1. var guiMode : String = "InGame";
    2. var numActivated : int;
    3. var totalLZ : int;
    4.  
    5. function start (){
    6.    
    7. }
    8.  
    9. function Update(){
    10.  
    11.     if(Input.GetKeyDown("escape")){
    12.         Time.timeScale = 0;
    13.         guiMode = "Paused";
    14.     }
    15.    
    16. }
    17.  
    18. function OnGUI(){
    19.     if(guiMode == "Paused"){
    20.         if(GUI.Button(Rect(Screen.width/2-75,Screen.height/2-20,150,30),"Resume Game")){
    21.             Time.timeScale = 1;
    22.             guiMode = "InGame";
    23.             print("starting new game...");
    24.         }
    25.         if(GUI.Button(Rect(Screen.width/2-75,Screen.height/2+20,150,30),"Quit to Main Menu")){
    26.             Time.timeScale = 1;
    27.             print("continue game...");
    28.             Application.LoadLevel(0);
    29.         }
    30.     }
    31.     if(guiMode == "Win"){
    32.         if(GUI.Button(Rect(Screen.width/2-75,Screen.height/2-20,150,30),"Next Level")){
    33.             Time.timeScale = 1;
    34.             guiMode = "InGame";
    35.             Application.LoadLevel(Application.loadedLevel + 1);
    36.             print("Next level");
    37.         }
    38.         if(GUI.Button(Rect(Screen.width/2-75,Screen.height/2+20,150,30),"Quit to Main Menu")){
    39.             Time.timeScale = 1;
    40.             print("quiting...");
    41.             Application.LoadLevel(0);
    42.         }
    43.     }
    44.     if(guiMode == "Lose"){
    45.         if(GUI.Button(Rect(Screen.width/2-75,Screen.height/2-20,150,30),"Retry Level")){
    46.             Time.timeScale = 1;
    47.             guiMode = "InGame";
    48.             Application.LoadLevel(Application.loadedLevel);
    49.             print("Retry level");
    50.         }
    51.         if(GUI.Button(Rect(Screen.width/2-75,Screen.height/2+20,150,30),"Quit to Main Menu")){
    52.             Time.timeScale = 1;
    53.             print("quiting...");
    54.             Application.LoadLevel(0);
    55.         }
    56.     }
    57. }
    58.  
    59. function LZactivated(){
    60.     numActivated++;
    61.     if(numActivated == totalLZ){
    62.         Win();
    63.     }
    64. }
    65.  
    66. function Win(){
    67.     guiMode = "Win";
    68.     Time.timeScale = 0;
    69.     PlayerPrefs.SetInt("playerLevel",Application.loadedLevel+1);
    70. }
    71.  
    72. function Lose(){
    73.     Wait();
    74. }
    75.  
    76. function Wait(){
    77.    
    78.     yield WaitForSeconds(1.5);
    79.     Time.timeScale = 0;
    80.     guiMode = "Lose";
    81. }
     
  4. Deleted User

    Deleted User

    Guest

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

    YKpro

    Joined:
    May 14, 2013
    Posts:
    12
    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.
     
  6. cdevl

    cdevl

    Joined:
    Apr 10, 2013
    Posts:
    180
    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.
     
  7. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    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 ;) it's backend processing voodoo if not :p
     
  8. cdevl

    cdevl

    Joined:
    Apr 10, 2013
    Posts:
    180
    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 :) ) because what gets yielded is the Wait() and nothing else.
     
  9. YKpro

    YKpro

    Joined:
    May 14, 2013
    Posts:
    12
    i tried this:
    Code (csharp):
    1. function Explode(){
    2.     Gui.Lose();
    3.     Instantiate(explosion,transform.position,Quaternion.identity);
    4.     yield WaitForSeconds(2);
    5.     Destroy(gameObject);
    6. }
    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:

    Code (csharp):
    1. function Lose(){
    2.     //Wait();
    3.     yield WaitForSeconds(1.5);
    4.     Time.timeScale = 0;
    5.     guiMode = "Lose";
    6. }
    so there is 0.5 seconds ahead of the destroy. so it worked!

    I think LeftyRighty is right.:D

    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.