Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 /
avatar image
0
Question by Essential · Sep 29, 2013 at 01:40 AM · functionloopyieldmethodwhile

while loop not looping

I'm sure I've done this same thing many times before, but this time it doesn't appear to be working. The code will print Time only once and then will quit the function on the yield.

 function Boost ()
 {
     var destTime = Time.time + 20;
     while ( Time.time < destTime )
     {
         Debug.Log ( Time.time );
         yield;
     }
     Debug.Log( "Loop complete" );    // <~~ This is never reached
 }
Comment
Add comment · Show 3
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 Eric5h5 · Sep 29, 2013 at 02:25 AM 1
Share

There's nothing wrong with that code by itself; you're doing something elsewhere (maybe destroying the object or something).

avatar image Essential · Sep 29, 2013 at 03:31 AM 0
Share

Okay, I figured out what's causing it but I have no idea how or why.

What calls this function is an item. If the item is collected, it calls this function remotely telling the other script to Boost() and then deactivates itself. If the item doesn't deactivate itself after calling the function, the while loop runs correctly, but when it deactivates itself the loop runs once and quits at yield.

But why is this happening? The item that is deactivating itself is calling a function on a completely separate gameObject. Whether it is deactivated or not should have no bearing on the Boost() function above. :S

avatar image Eric5h5 · Sep 29, 2013 at 03:57 AM 0
Share

That's not any behavior I've seen, and I can't replicate it now. Whenever you come across something "weird", make the simplest possible repro case and see if the behavior happens. If not (which is nearly always), keep adding more logic from the original code until you find out where it's going wrong. This may seem time-consu$$anonymous$$g, but it will typically save you a lot of problems later on since you won't have to rely on hacks that may or may not "fix" the problem.

2 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by Jamora · Sep 29, 2013 at 11:39 AM

Coroutines are run on the GameObject that had the script that called StartCoroutine. Note that in UnityScript the StartCoroutine is implied, if the function has a yield in it.

So, let's say you have a player and an item. If you have the Player call Boost() on the item, the Boost() coroutine will be run on the Player's GameObject. If you have the Item call Boost(), the coroutine will be run on the Item's GameObject.

You can see this behavior with the following scripts:

 //MyBaseClass.cs
 //Attached to a GameObject named "1"
 using UnityEngine;
 using System.Collections;
 
 public class MyBaseClass : MonoBehaviour {
     
     public void StartCor(){
         StartCoroutine(Cor ());
     }
     
     public IEnumerator Cor(){
         while(true){
             Debug.Log("coroutine");
             yield return null;
         }
     }
 }
 
 //MyExtendedClass.cs
 //Attached to another GameObject
 using UnityEngine;
 
 public class MyExtendedClass : MonoBehaviour {
     void Start(){
         //StartCoroutine(GameObject.Find("1").GetComponent<MyBaseClass>().Cor());
         GameObject.Find("1").GetComponent<MyBaseClass>().StartCor();
     }
 }

Depending on who called StartCoroutine, disabling that GameObject will also stop the coroutine.

Your problem will most likely be solved by calling Boost() from somewhere else than the Item script.

Comment
Add comment · Show 2 · 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 Fattie · Sep 29, 2013 at 01:02 PM 1
Share

"disabling that GameObject will also stop the coroutine"

Just to be clear for new chums, coroutines run independently of the enabled property of a component.

They just keep runnin' and runnin' if you enable=false a component

You have to SetActive(false) on the whole gameObject to stop a coroutine. Or, you can literally Destroy the component (the script attached, that is to say) in question.

So run the test below. In the editor in Inspector, turn on an off (enabled property) the check box on the Teste component. The coroutine keeps going with a life of its own.

In contrast turn off the whole gameObject (checkbox at top) and it finally stops. It's well worth noting that if you make it active again (same checkbox), the coroutine does not "carry on as it was".

If you are new it's worth remembering those two checkboxes in Inspector (for the gameObject, and in some cases for the individual components) are utterly different things.

So that's what Jamora is saying here.

using UnityEngine; using System.Collections;

public class Teste : $$anonymous$$onoBehaviour { void Start () { StartCoroutine(teste()); Invoke("blockme",10.5f); }

 IEnumerator teste()
     {
     while (true)
         {
         if (enabled) Debug.Log("yeah it is enabled");
         else Debug.Log("it's not enabled but I don't give a stuff I am still running.");
         
         Debug.Log("yo I am running ......");
         yield return new WaitForSeconds(0.25f);
         }
     }
 
 void blockme()
     {
     enabled = false;
     // but, try this .... DestroyImmediate(GetComponent<Teste>()); 
     }
 
 }
avatar image Essential · Sep 29, 2013 at 10:51 PM 0
Share

Thanks for the input, Jamora. Why is the original GameObject still a factor, even if it has nothing to do with the coroutine it called? Seems kinda strange.

It's appropriate for the Coroutine to end early if the GameObject the Coroutine is currently running on is made inactive. I don't see how it makes sense for the Coroutine to end early if the GameObject that called the function is made inactive. It's like your sidekick is dying at the end of the movie and with his last dying breath he says, "Push the button to stop the explosion! " and so the hero runs over to push the button but then stops and turns back, sees his sidekick die, and decides it doesn't need to be pushed anymore. :P

avatar image
1

Answer by Kiloblargh · Sep 29, 2013 at 03:11 AM

The yield is probably the problem.

But that's not the right way to use a while loop, anyway. Either use InvokeRepeating or set a boolean (isBoosted) and do something in Update() if the boolean is true. Define your destTime variable in the main script, not in the function that sets it.

Comment
Add comment · Show 4 · 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 Essential · Sep 29, 2013 at 03:28 AM 0
Share

I try to avoid using Update() unless my script is doing something every frame (which this isn't). In retrospect I may do an invokerepeating next time I'd code something like this.

avatar image Eric5h5 · Sep 29, 2013 at 03:52 AM 1
Share

The yield is not a problem, and it's a perfectly acceptable way to use a while loop. Coroutines are generally easy to use and quite useful. The only thing I'd stay away from is Time.time, since that's a single-precision float, which degrades in precision over time. I'd generally stay away from Update unless necessary, since you'd be forced to use a global variable as you note (local is to be preferred where feasible), among other things.

avatar image Essential · Sep 29, 2013 at 06:38 PM 0
Share

Just curious Eric, what do you recommend ins$$anonymous$$d of using time?

avatar image Eric5h5 · Sep 29, 2013 at 07:52 PM 0
Share

It depends, but probably DateTime would be typical. Time.time is fine if your app won't ever run for very long, but in those cases where it might run for days or weeks at a time (like in a kiosk), it can be problematic.

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

18 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

Related Questions

Yield Not Working - While Loop 3 Answers

Have a function wait unitl a boolean is false 1 Answer

Re-using the "same" for loop? 1 Answer

How do I call a function containing a while loop, inside the update function? 2 Answers

Trying to Loop A Function 2 Answers


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