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 /
avatar image
0
Question by hulahoolgames · Jan 14, 2016 at 09:36 PM · coroutinescoroutine errorshang

Concurrent coroutines working on same datastructure hang unity!

I have a list of gameobjects that represent the nodes of snake character in my game. I have 2 coroutines, one that adds more nodes to this list, and one that pulls all the nodes towards the head node when a certain condition is met. This pull coroutine is basically just sucking all the nodes towards the first node position using a lerp on their positions. But sometimes when the pull coroutine and the increment length coroutine run concurrently unity hangs.

  // This is the pull coroutine
  IEnumerator Pull() {
             List<GameObject> nodes = GameObjectAccessor.instance.getSnakeData().getSnakeNodes();
             Vector3 [] positions = new Vector3[nodes.Count + 1];
             positions[0] = m_orbPos;
             for(int i = 1; i < positions.Length; i++) {
                 positions[i] = nodes[i - 1].transform.position;
             }
             float distTailTravels = (nodes.Count - 1) * getGreedyHeadScale();
             float pullSpeed = distTailTravels / orbPullTime;
             float targetResetTime = getGreedyHeadScale() / pullSpeed;
             float lastResetTime = 0.0f;
             int targetOffset = 1;
             bool finished = false;
     
             while(!finished) {
                 Logger.Log("Starting Pull");
                 if(lastResetTime > targetResetTime) {
                     targetOffset++;
                     lastResetTime = 0.0f;
                 }
                 for(int i = 1; i < positions.Length; i++) {
                     if(i - targetOffset >= 0) {
                         Vector3 destination = positions[i - targetOffset];
                         nodes[i - 1].transform.position = Vector3.Lerp(nodes[i - 1].transform.position, destination, pullSpeed * Time.deltaTime);
                     } else {
                         nodes[i - 1].transform.position = positions[0];
                         nodes[i - 1].transform.rotation = nodes[0].transform.rotation;
                         NewSnakeMovement bodyMovement = nodes[i - 1].GetComponent<NewSnakeMovement>();
                         bodyMovement.resetTarget(positions[0]);
                         if(i == positions.Length - 1 && nodes[i - 1].transform.position == positions[0]) {
                             finished = true;
                             Logger.Log("######################### Pull completed ###########################");
                         }
                     }
                 }
     
                 yield return null;
                 lastResetTime += Time.deltaTime;
             }
             GameObjectAccessor.instance.getSnakeData().decrementLengthOnEvolution();
             incrementScale();
             // start countdown
             GamePlayScreen.instance.go();
     }
     
     // This is the coroutine to increment length
     IEnumerator incrementLengthCoroutine(int value) {
             Logger.Log("Starting increment coroutine");
             GameObject tail = null;
             if (mSnakeNodes.Count > 1) {
                 tail = mSnakeNodes[mSnakeNodes.Count - 1];
                 GameObject tailParent = mSnakeNodes[mSnakeNodes.Count - 2];
                 mSnakeNodes.RemoveAt(mSnakeNodes.Count - 1);
                 tailParent.GetComponent<NewSnakeMovement>().ChildNode = null;
             }
             if(tail != null) {
     //            tail.GetComponent<NewSnakeMovement>().pauseForTime((value) * mSnakeMovement.getTimePerGrid());
                 tail.GetComponent<NewSnakeMovement>().pause();
             }
     
             for(int i = 0; i < value; i++) {
                 GameObject tailParent = mSnakeNodes[mSnakeNodes.Count - 1];
                 // get the body from pool
                 GameObject body = SnakeBodyPooler.instance.getObjectFromPool();
                 body.transform.position = tailParent.transform.position;
                 body.transform.rotation = tailParent.transform.rotation;
                 body.transform.localScale = tailParent.transform.localScale;
                 body.SetActive(true);
                 body.GetComponent<NewSnakeMovement>().pauseForTime((i) * mSnakeMovement.getTimePerGrid());
                 addSnakeNode(body);
                 yield return new WaitForEndOfFrame();
             }
     
            addSnakeNode (tail);
             tail.GetComponent<NewSnakeMovement>().unPause();
             Logger.Log("Ending increment coroutine");
     }
     
     // adds a node to the list
     public void addSnakeNode(GameObject node) {
             if(mSnakeNodes.Count > 0) {
                 GameObject lastNode = mSnakeNodes[mSnakeNodes.Count - 1];
                 NewSnakeMovement move = lastNode.GetComponent<NewSnakeMovement>();
                 move.ChildNode = node;
                 move.BodyIndex = mSnakeNodes.Count;
             }
             mSnakeNodes.Add(node);
         }

If I change the increment length coroutine to be a simple for loop that runs in one frame then i dont face this problem. Also, its the Pull coroutine that hangs, and once it does it does NOT even log the "Starting Pull" statement at the start of the while loop. So its not even going into an infinite loop. Let me know if anyone spots a major flaw with this code. I have been looking at it for hours and my mind maybe just skipping over something obvious. Any suggestions to modify this approach are welcomed too. Thanks in advance.

Comment
Add comment · Show 1
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 hulahoolgames · Jan 14, 2016 at 09:57 PM 0
Share

An update, it does not actually hang unity because all the other elements of my game are still running. Its just that the Pull coroutine does not complete execution and i think the problem might be I am saving the positions of nodes in an array when the Pull coroutine starts and I only loop through this positions array. So during execution if new nodes are added to the node list, the positions array does not get updated and this causes the if(i == positions.Length - 1 && nodes[i - 1].transform.position == positions[0]) { finished = true; Logger.Log("######################### Pull completed ###########################"); ter$$anonymous$$ating check to never hit. The last node now was never pulled to position[0] since it never got added in the positions array. I think this is the problem and need to fix this logic. Still doesn't explain why it does not log the statement on the start of the while loop if it never ter$$anonymous$$ates!

2 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by lassade · Jan 14, 2016 at 10:02 PM

Based ona quick look at your code a have some suggestions:

  1. You need to update the length of the positions vector every time you add more snake nodes. If you dont only a few nodes of the frist nodes will be moved. (if you want to run the coroutine like a second Update function)

  2. I not sure about the code that calls this coroutines but, both coroutines have ends. What i mean is by the time the finished variable in Pull is set to true the coroutine will end since it will reach the end of the function and will only start again if you call StartCoroutine(Pull())

  3. One common mistake is disable de gameObject (or script) that holds some coroutine, this will pause the coroutine (not sure if is the case in the .unPause(); and .pause(); functions).

Comment
Add comment · 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 hulahoolgames · Jan 15, 2016 at 09:26 AM 0
Share

It was indeed the issue with not updating the positions array. Thanks for the heads up on points 2 and 3 but those were already taken care of.

avatar image
0

Answer by wgt_jimmy · Jan 15, 2016 at 05:44 PM

How about only taking the last node and putting it at the head of the list in the new position it needs to be?

Comment
Add comment · 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

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

33 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 avatar image avatar image avatar image avatar image

Related Questions

Coroutine That was working previously not working in scene 0 Answers

Multiple coroutine exicution order 1 Answer

StopAllCoroutines not working 0 Answers

Unity hangs when trying to load an image from url using the WWW class 1 Answer

Coroutine only fires once instead of looping until stopped. 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