Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by CUTCUTCUT · Sep 15, 2015 at 11:03 AM · coroutinewaitforsecondsignore

Coroutine not waiting for yield WaitForSeconds [JS]

I have been working on a Sanity level of a player and I've been using Coroutines to drain 5 sanity every second and that Coroutine I am using is just ignoring WaitForSeconds. I need help.

 function SanityDraining(){
   
  if(lanternLight.enabled == false){
   
   StartCoroutine(sanityDrain(1.0));
 
  }else{
  
    StopCoroutine(sanityDrain(1.0));
 
   }
  
 }
 
 function sanityDrain(waitTime : float){
    playerSanity = playerSanity - sanityLoss;
    yield WaitForSeconds(waitTime);
 }

I have called the Sanity Draining function in Update function and its working, everything is working but its just ignoring yield. I have a script that I've done with players light, also using coroutines and it works perfectly. I dont know what seems to be the problem here.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by Dave-Carlile · Sep 15, 2015 at 12:09 PM

Are you expecting the Coroutine to continue draining the sanity over time? That's what would happen if you're calling that in update. But as a Coroutine it's only going to subtract sanityLoss one time, wait for 1 second, then quit. If you want it to continue draining over time then the Coroutine needs to be a loop...

 function sanityDrain(waitTime : float)
 {
   while (playerSanity > 0)
   {
     playerSanity -= sanityLoss;
     yield WaitForSeconds(waitTime);
   }
 }

This will loop while sanity is greater than 0, waiting for waitTime seconds for each iteration.

Comment
Add comment · Show 12 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image CUTCUTCUT · Sep 15, 2015 at 12:22 PM 0
Share

It is working but its still not waiting for that one second. It just drains all the sanity to 0 in a second.

avatar image Dave-Carlile · Sep 15, 2015 at 12:27 PM 0
Share

Add a Debug.Log at the beginning and log the value of the 3 variables (playerSanity, sanityLoss, waitTime). $$anonymous$$ake sure they're actually what you think they are.

Also, how do you call SanityDraining? Is that only being called once? If you're accidentally calling that each frame you're going to start multiple Coroutines and each one of them is going to reduce playerSanity and it will go to 0 very fast. Add a Debug.Log there too and make sure it's only called once when the lantern state changes.

avatar image CUTCUTCUT Dave-Carlile · Sep 15, 2015 at 12:41 PM 0
Share

Debug.Log shows no problems. I called SanityDraining in Update function.

 function Update () {
 
  SanityDraining();
 
  if(playerSanity <= 0){
   Application.LoadLevel("Death");
  }
  
 }
avatar image Dave-Carlile CUTCUTCUT · Sep 15, 2015 at 12:55 PM 0
Share

Calling that in update is your problem. It's going to start a coroutine every frame. So for example by frame 3 you'll have 3 of those coroutines running, and each of them will be looping and reducing playerSanity. So it's going to be reduced to 0 very fast - nearly instantly.

You only want to call SanityDraining when the state of the lanternLight changes. You want to call it at the same time you change the value of lanternLight.enabled - presumably where you're checking for input to turn the lamp on or off.

Show more comments
Show more comments
avatar image Dave-Carlile · Sep 15, 2015 at 01:21 PM 0
Share

I don't know how your trigger is set up, but it would seem it's still causing your coroutine to be started multiple times. Add a Debug.Log right before your call to StartCoroutine and you should see that it's being started multiple times.

If you double click on the error message it will take you to the line that's causing the problem. You're accessing a variable that is null.

avatar image CUTCUTCUT Dave-Carlile · Sep 15, 2015 at 01:38 PM 0
Share

Coroutine is started 2 times when lantern is turned off and every time i move it adds starts another coroutine every second.

 #pragma strict
 
 var plSanity : player_Sanity;
 var lanternTrigger : GameObject;
 var lanternLight : Light;
 
 public var playerSanity : int = 100;
 public var sanityLoss : int = 1;
 
 function Start () {
  lanternLight = GetComponentInParent.<Light>();
  lanternTrigger.SetActive(false);
 
 }
 
 function Update () {
  if(lanternLight.enabled == false){
   lanternTrigger.SetActive(true);
   }else{
    lanternTrigger.SetActive(false);
    }
  if(playerSanity <= 0){
   Application.LoadLevel("Death");
  }
  
 }
 
 function OnTriggerEnter(){
 
  if(lanternTrigger.activeSelf == true){
   Debug.Log("Coroutines are multiplied");
   StartCoroutine("sanityDrain");
 
  }else{
  
    StopCoroutine("sanityDrain");
 
   }
 
 }
 
 
  function sanityDrain()
  {
    while (playerSanity > 0)
    {
      playerSanity = playerSanity - sanityLoss;
      yield WaitForSeconds(1);
    }
  }
 
 function OnGUI () {
 GUI.Box(Rect(10,40,100,25),"Sanity:");
 GUI.Box(Rect(110,40,100,25),playerSanity.ToString());
 }
 
avatar image Dave-Carlile CUTCUTCUT · Sep 15, 2015 at 01:54 PM 0
Share

Right, your trigger is being triggered as you move. Where do you actually turn the lamp on or off? It seems that it would make more sense to start the sanity drain there. Otherwise, you can check for state changes by tracking the last state...

Go back to the version without the trigger, but with the looping coroutine...

 // declare a variable in your class to hold the last state
 bool lastState;

 // initialize the last state to the current lantern state
 function Start()
 {
     ...
     lastState = lanternLight.enabled;
 }


 // modify your SanityDraining function to only do things on state changes
 function SanityDraining()
 {
     // if the light is still in the last state then don't do anything
     if (lanternLight.enabled == lastState) return;

     // otherwise the light state has changed so we want to kick off
     // the appropriate coroutine
     if (!lanternLight.enabled)
     {
         StartCoroutine(sanityDrain(1.0));
     }
     else
     {
         StopCoroutine(sanityDrain(1.0));
     }

     // finally we need to remember the last state so we won't
     // do anything here until that state changes again
     lastState = lanternLight.enabled;
 }
Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

29 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to implement pausing of WaitForSeconds based coroutine? 1 Answer

Call Coroutine step after step in foreach loop 0 Answers

Coroutine WaitForSeconds ignoring StopAllCoroutines... How can I do it? 0 Answers

Wait time after coroutine's wait seconds is complete 0 Answers

Coroutine not working 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges