Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 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 gilneto8 · Nov 05, 2015 at 06:45 AM · scripting problemmultiplecoroutinesupdate functionfreezing

Multiple coroutines starting from Update() freeze/crash Unity

I'm having a problem with a script I'm developing.

The idea is to move a character from A(x,y) to B(x',y') in a 2D top-down grid-like map. I've done all the path calculations and the coroutine I'm using is working. The problem is, it works if I don't try to call it again before its completion. In other words and using an example: suppose I'm in A(x,y) and want to go to B(x',y'). I click the map, the calculations are made, the path is set and the coroutine starts. While the character is walking, I suddenly want to change directions and go to C(x'',y''). At this point, if I click the map again, Unity just freezes, while occupying more and more memory, and later on it crashes.

Maybe someone can help me figure this out. I've tried updating a boolean between true and false to use as a flag outside the coroutine, and also tried to call the StopCoroutine function, to no avail. If you have any idea as to why this is happening, please help.

Here's the code, by the way:

 class PlayerScript : MonoBehaviour {


 public GameObject map_go;
 public float speed;

 private Map map;
 private List<Vector3> path;

 public void Start() {
     path = new List<Vector3>();
     map = map_go.GetComponent<Map>();
     StartCoroutine(move());
 }

 public void Update() {
     Vector3 clickpoint = transform.position;
     Vector3 destination;

     bool clicked = false;
     if (Input.GetMouseButtonDown(0)) { 
         clickpoint = Camera.main.ScreenToWorldPoint(Input.mousePosition); 
         clicked = true; 
     }
     else if (Input.touchCount > 0) {
         clickpoint = Camera.main.ScreenToWorldPoint(new Vector3 
                                                   (Input.GetTouch(0).position.x, 
                                                     Input.GetTouch(0).position.y, 
                                                    transform.position.z));
         clicked = true;
     }

     if (clicked) {
         int dest_x = Mathf.RoundToInt(clickpoint.x);
         int dest_y = Mathf.RoundToInt(clickpoint.y);
         destination = new Vector3(dest_x, dest_y,transform.position.z);
         
         path = map.calculatePath(transform.position, destination);
         //StartCoroutine(move(path));
     }
 }

 IEnumerator move () {
     Vector3 dest = Vector3.zero;
     while (true) {
         while (path.Count == 0) yield return null;

         for (int i = 0; i < path.Count; i++) {
             dest = path[i];
             Vector3 src = transform.position;
             float step = (speed / (src - dest).magnitude) * Time.fixedDeltaTime;
             float t = 0;
             while (t <= 1.0f) {
                 t += step;
                 transform.position = Vector3.Lerp (src,dest,t);
                 yield return new WaitForFixedUpdate();
             }
             transform.position = dest;
         }
         path = new List<Vector3>();
     }
 }

 }

Thanks in advance!

Comment
Add comment · Show 2
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 gjf · Nov 04, 2015 at 09:36 PM 1
Share

try starting your coroutine from Start() and have it wait until you've got a path to follow then run your current code from move - just have it do a yield return null if you're waiting.... the overhead from having it wait without a path is negligible, and faster in overall performance than starting a coroutine.

also, move the GetComponent from Update() to Start() - there's no need to do it every Update(), unless map_go changes... in which case use a getter/setter for it and get the component when you set map_go.

hope that helps.

avatar image gilneto8 gjf · Nov 04, 2015 at 09:51 PM 0
Share

Thanks for the answer.

Following your instructions, I ended up with the following result:

 class PlayerScript : $$anonymous$$onoBehaviour {
 
 
     public GameObject map_go;
     public float speed;
 
     private $$anonymous$$ap map;
     private List<Vector3> path;
 
     public void Start() {
         map = map_go.GetComponent<$$anonymous$$ap>();
         StartCoroutine(move());
     }
 
     public void Update() {
         Vector3 clickpoint = transform.position;
         Vector3 destination;
 
         bool clicked = false;
         if (Input.Get$$anonymous$$ouseButtonDown(0)) { 
             clickpoint = Camera.main.ScreenToWorldPoint(Input.mousePosition); 
             clicked = true; 
         }
         else if (Input.touchCount > 0) {
             clickpoint = Camera.main.ScreenToWorldPoint(new Vector3 
                                                       (Input.GetTouch(0).position.x, 
                                                         Input.GetTouch(0).position.y, 
                                                        transform.position.z));
             clicked = true;
         }
 
         if (clicked) {
             int dest_x = $$anonymous$$athf.RoundToInt(clickpoint.x);
             int dest_y = $$anonymous$$athf.RoundToInt(clickpoint.y);
             destination = new Vector3(dest_x, dest_y,transform.position.z);
             
             path = map.calculatePath(transform.position, destination);
 
             //StartCoroutine(move(path));
         }
     }
 
     IEnumerator move () {
         while (true) {
             while (path == null) yield return null;
 
             foreach (Vector3 dest in path) {
                 Vector3 src = transform.position;
                 float step = (speed / (src - dest).magnitude) * Time.fixedDeltaTime;
                 float t = 0;
                 while (t <= 1.0f) {
                     t += step;
                     transform.position = Vector3.Lerp (src,dest,t);
                     yield return new WaitForFixedUpdate();
                 }
                 transform.position = dest;
             }
             path = null;
         }
     }
 
 }


The Good News: thanks for the tip on the GetComponent, totally forgot about that. And the coroutine always running on the background is also a pretty nice touch.

The Bad News: still crashing Unity when I try to start another move while the first is occurring. $$anonymous$$aybe I didn't understand your instructions clearly, but I suppose this was the result you were thinking...

0 Replies

· Add your reply
  • Sort: 

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

3 People are following this question.

avatar image avatar image avatar image

Related Questions

How to an animation clip based on characters(letters) in an array 1 Answer

How to increment score by one, every time player moves the device face down ? 2 Answers

WaitForSeconds using Update? 1 Answer

Coroutine not working properly 1 Answer

Synchronization in execution of methods of a class using co-routines. 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