• 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
Question by boddole · Jan 24, 2015 at 03:44 AM · c#coroutineyieldcoroutines

Trouble Resuming after Yielding while Inside Coroutine

Hello everyone, I'm having trouble with yielding for a coroutine (then resuming execution) while inside another coroutine, where yielding to another coroutine causes the original coroutine to never complete (it just ends after the yield instuction. More details below:

The Script:

     private IEnumerator InitialSpawnLogic()
     {
         Debug.Log("InitialSpawnLogic() coroutine starting...");
 
         #region Dealing with Initial Spawning:
         //figure out if a player/npc are needed or some other combo:
 
         //we always need a player ship:
         yield return StartCoroutine(ChooseSpawnAndInstantiateShip(currentPlayerShip, false) ); //select a good spawn point, instantiate Player...
 
         //need an NPC ship unless TRAINING is detected:
         if(currentGameMode != GameModes.Training)
         {
             Debug.Log("the GAMEMODE seleteced requires at least 1 NPC ship...");
 
             //now get NPC:
             Debug.Log("1111");
 
             yield return StartCoroutine (ChooseSpawnAndInstantiateShip(currentNPCShip, true) ); //select a good spawn point, instantiate NPC..
 
             Debug.Log("2222");
         }
         else
         {
             Debug.Log("the GAMEMODE seleteced does NOT require any NPC ship(s)...");
         }
         #endregion Dealing with Initial Spawning:
 
         Debug.Log("3333");
 
         //check game type to either start recurring spawn logic or not:
         if(currentGameMode == GameModes.Survival) //for now, RANDOM is only 1v1 battles (since that is the "free default", so don't account for it)...
         {
             Debug.Log("currentGameMode == GameModes.Survival");
             StartCoroutine("RecurringSpawnLogic");
         }
         else
         {
             Debug.Log("This game type does not require Re-spawns, InitialSpawnLogic() coroutine ending");
         }
     }

In Detail:

The InitialSpawnLogic coroutine never gets to the "Debug("2222")" line or beyond. What confuses me is that there does not seem to be any problem the first time I yield, and the method it yields to ends the same way regardless of the arguments passed in. So, why does the script continue to execute the first time but not the second?

Any ideas are appreciated, thank you for reading.

UPDATE 2: Turns out an issue with Nav Meshes on the created ships was stalling the script, problem fixed.

UPDATE: (as requested, here are the other methods in question)

     //get valid spawn point, then instantiate Ship:
     private IEnumerator ChooseSpawnAndInstantiateShip(ShipTypes desiredShipType, bool isNPCShip)
     {
         Debug.Log("ChooseSpawnAndInstantiateShip() coroutine started...");
 
         yield return StartCoroutine(GetSpawnPoint() ); //grab a valid spawn point for the incoming ship...
         Debug.Log("valid spawn point found for new ship...");
 
         GameObject ship; //becomes the instantiated prefab...
 
         if(isNPCShip)
         {
             //create a new GO parent of the instan.GO, attatch the script to it (so the prefab can get NPC/Player controll):
             GameObject npcShipGOParent = new GameObject();
             npcShipGOParent.name = "NPCShip";
             npcShipGOParent.transform.parent = parent_NPCShips;
             Ship_ControlSetter sCS = npcShipGOParent.AddComponent<Ship_ControlSetter>();
             sCS.ShipControlledBy = ShipControlledBy.NPC;
             
             //Debug.Log("Manager_ShipSpawning: ChooseSpawnAndInstantiateShip() Breaking");
             //Debug.Break();
 
             //instantiate ship at spawn point:
             if(desiredShipType != 0) //random ship desired...
             {
                 ship = (GameObject) Instantiate(shipArray[(int) desiredShipType], tempSpawnLocation, Quaternion.identity);
                 Debug.Log("new NPC ship of value: " + (int) desiredShipType + " should have been instantiated");
                 ship.transform.parent = npcShipGOParent.transform;
             }
             else //random ship is desired:
             {
                 ship = (GameObject) Instantiate(shipArray[Random.Range(1, shipArray.Length)], tempSpawnLocation, Quaternion.identity); //1 because of enum values...
                 Debug.Log("new randomized NPC ship should have been instantiated");
                 ship.transform.parent = npcShipGOParent.transform;
             }
         }
         else //Player ship...
         {
             //create a new GO parent of the instan.GO, attatch the script to it (so the prefab can get NPC/Player controll):
             GameObject playerShipGOParent = new GameObject();
             playerShipGOParent.name = "PlayerShip";
             playerShipGOParent.transform.parent = parent_PlayerShips;
             Ship_ControlSetter sCS = playerShipGOParent.AddComponent<Ship_ControlSetter>();
             sCS.ShipControlledBy = ShipControlledBy.Player;
 
             //Debug.Log("Manager_ShipSpawning: ChooseSpawnAndInstantiateShip() Breaking");
             //Debug.Break();
 
             //instantiate the player ship at the chosen spawn point:
             if(desiredShipType != 0) //specific ship desired...
             {
                 ship = (GameObject) Instantiate(shipArray[(int) desiredShipType], tempSpawnLocation, Quaternion.identity);
                 Debug.Log("new Player ship of value: " + (int) desiredShipType + " should have been instantiated");
                 ship.transform.parent = playerShipGOParent.transform;
             }
             else //random ship is desired:
             {
                 ship = (GameObject) Instantiate(shipArray[Random.Range(1, shipArray.Length)], tempSpawnLocation, Quaternion.identity); //1 because of enum values...
                 Debug.Log("new randomized Player ship should have been instantiated");
                 ship.transform.parent = playerShipGOParent.transform;
             }
 
             #region set ship correctly for Player Usage:
             //the pathfinding GO and and NPC logic script need to get disabled/turned off:
             Debug.Log("Manager_ShipSpawning disabling NPC components for Player Ship use...");
             Transform pathfindingTrans = ship.transform.FindChild("Pathfinder");
             pathfindingTrans.gameObject.GetComponent<NavMeshAgent>().enabled = false;
             pathfindingTrans.gameObject.SetActive(false);
 
             ship.GetComponentInChildren<NPC_Logic>().enabled = false;
             //Debug.Log("ship.GetComponentInChildren<NPC_Logic>().enabled = false");
             #endregion set ship correctly for Player Usage:
         }
 
         #region Final Setups for NPC/Player ships:
         Ship_Initializer shipInitializer = ship.GetComponentInChildren<Ship_Initializer>();
         shipInitializer.SetupShip();
         
         UI_ObjectTracker.ui_ObjectTracker.Activate();
         #endregion Final Setups for NPC/Player ships:
 
         yield return null; //wait to make sure 2 ships don't get spawned on top of each other in the same frame...
     }
 
     //use this to effectively "lock up" Instantiation coroutines if no new spawn point is available:
     private IEnumerator GetSpawnPoint()
     {
         Debug.Log("GetSpawnPoint() coroutine started");
 
         //get valid spawn point:
         while(true)
         {
             Debug.Log("GetSpawnPoint() coroutine running...");
 
             tempSpawnLocation = spawnTransList[Random.Range(0, spawnTransList.Count)].transform.position;
             Debug.Log("tempSpawnLocation is: " + tempSpawnLocation);
 
             //Debug.Log("Manager_ShipSpawning: GetSpawnPoint() breaking");
             //Debug.Break();
 
             //now test to see if the spawnpoint is valid:
             if(!Physics.CheckSphere(tempSpawnLocation, spawnSafeRadius, layersToCheckAgainst) ) //if nothing is hit in layermask...
             {
                 //Debug.Log("ManagerShipSpawning: GetSpawnPoint() breaking");
                 //Debug.Break();
 
                 yield break;
             }
             else
             {
                 Debug.Log("randomly selected spawnpoint was not valid, trying again...");
                 yield return new WaitForSeconds(1f); //done to minimize collider checks per frame...
             }
         }
     }

Comment

People who like this

0 Show 7
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 SilentSin · Jan 24, 2015 at 03:49 AM 0
Share

Post the ChooseSpawnAndInstantiateShip method.

avatar image boddole · Jan 24, 2015 at 04:08 AM 0
Share

@SilentSin

Post Updated. I'm guessing based on your request that there isn't something obviously wrong with the first coroutine, so I'm messing something up in one/both of the others?

avatar image pako · Jan 24, 2015 at 10:26 AM 0
Share

I suspect that the problem is in the while(true) loop inside the IEnumerator GetSpawnPoint(). I think that neither yield break; nor yield return new WaitForSeconds(1f); will actually end the while(true) loop, which will just endlessly keep yielding either break or WaitForSeconds.

So, it seems that the coroutine cannot be started a second time in line 19, because it's still running.

avatar image SilentSin · Jan 24, 2015 at 10:29 AM 0
Share

Yeah, that'll be it. The yield is preventing the break from actually doing its job.

It won't stop the coroutine from starting a second time though. You can have as many instances of a coroutine going as you want. In this case, you'll slowly leak memory indefinitely because none of them can finish.

avatar image pako · Jan 24, 2015 at 10:51 AM 0
Share

Actually in one of my apps, if I tried to start the same coroutine more than once, I didn't have the expected results. Sometimes it would start, sometimes it wouldn't. So I prefer to avoid going that way.

Show more comments

1 Reply

  • Sort: 
avatar image

Answer by SilentSin · Jan 24, 2015 at 04:20 AM

Put some logs into ChooseSpawnAndInstantiateShip to see where its actually getting to. Maybe yield return StartCoroutine(GetSpawnPoint()); isn't returning or something.

Also, in GetSpawnPoint you don't need to yield break, you can just break. A coroutine needs to have at least one yield in it, but it doesn't actually need to get called in every code path.

Comment
boddole

People who like this

1 Show 1 · 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 boddole · Jan 24, 2015 at 11:08 AM 0
Share

Thank you for the tip on the yield. Turns out that a warning related to Nav Meshes on the instantiated ships was preventing the other coroutines from executing properly, once that was resolved everything worked as expected.

Unity Answers is in Read-Only mode

Unity Answers content will be migrated to a new Community platform and we are aiming to launch a public beta by June 9. Please note, Unity Answers is now in read-only so we can prepare for the final data migration.

For more information and updates, please read our full announcement thread in the Unity Forum.

Follow this Question

Answers Answers and Comments

21 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

Related Questions

Coroutines and states 1 Answer

Stop the Awake() until a user clicks a button? 1 Answer

Coroutine Won't Stop Using IEnumerator 1 Answer

What am I doing wrong with IEnumerator? 1 Answer

StartCoroutine() and yield return www does not work with Unity Web Player build 0 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