Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 11 Next capture
2021 2022 2023
1 capture
11 Jun 22 - 11 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 /
This question was closed Jul 23, 2015 at 11:29 AM by meat5000 for the following reason:

You are going to need a new approach. The code is very intensive and has multiple instances of recursion as well as too many ways it can break. Try splitting it up in to smaller chunks. Simplify!

avatar image
0
Question by Vini7x · Jul 22, 2015 at 04:55 AM · pathfindingfreezegrid based game

Path finding freezes Unity

So I am trying to create a path finding code for a turn-based game in a grid environment, I rewrote my code a lot of times in different ways, but it always ends freezing Unity, and I can't find out whats wrong.

     private void Move (GameObject t, GameObject c)
     {
         Debug.Log("Cheking at " + c.name);
         if (t.gameObject.GetComponent<TileProps> ().walkable && !t.GetComponent<TileProps>().occupied) {
             
             Collider[] nT = Physics.OverlapSphere(c.transform.position, tileSize);
             
             List<GameObject> neighbors = new List<GameObject>();
             
             foreach(Collider z in nT){
 
                 neighbors.Add(z.gameObject);
                 
             }
             
             for(int i = 0; i < neighbors.Count; i++){
                 Debug.Log(neighbors[i].name);
                 if(!neighbors[i].GetComponent<TileProps>().walkable || neighbors[i].GetComponent<TileProps>().occupied || checkedTiles.Contains(neighbors[i])){
                     
                     neighbors.Remove(neighbors[i]);
                     
                 }
                 
             }
             
             if(neighbors.Count > 0){
                 
                 for(int i = 0; i < neighbors.Count; i++){
 
                     checkedTiles.Add(neighbors[i]);
                     tempList.Add(neighbors[i]);
 
                     if(neighbors[i] != t){
 
                         Debug.Log("Looping...");
                         Move(t, neighbors[i]);
 
                     }else{
 
                         if(tempList.Count < numOfTiles){
 
                             tilesToMove = tempList;
                             numOfTiles = tempList.Count;
                             tempList.RemoveRange(0, tempList.Count);
 
                         }
 
                         if(checkedTiles.Count == mapM.GetComponent<MapManager>().tiles.Count){
                             
                             checkedTiles.RemoveRange(0, checkedTiles.Count);
                             Debug.Log("Path Calculated");
                             
                             if(numOfTiles <= actionP){
                                 
                                 StartCoroutine(Move2());
                                 
                             }else{
                                 
                                 Debug.Log("Not enough action points.");
                                 
                             }
                             
                         }
 
                     }
                 }
                 
             }else{
 
                 Debug.Log("Target is not walkable");
                 return;
                 
             }
 
         }
     }
Comment
Add comment · Show 5
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 Vini7x · Jul 22, 2015 at 08:45 PM 0
Share

Yes, I did many times, but I still don't know why the loop never ends

avatar image meat5000 ♦ · Jul 22, 2015 at 09:45 PM 0
Share

What does $$anonymous$$ove2() look like?

avatar image Vini7x · Jul 22, 2015 at 09:59 PM 0
Share

$$anonymous$$ove2() is the function that moves the character, I didn't included it in the question because I already tested it before and it worked without any problems, here's the code:

     private IEnumerator $$anonymous$$ove2 ()
     {
 
         for (int y = 0; y < tilesTo$$anonymous$$ove.Count; y++) {
         
             while (transform.position != tilesTo$$anonymous$$ove[y].transform.position) {
 
 
                 if (Vector3.Distance (transform.position, tilesTo$$anonymous$$ove [y].transform.position) < 0.2f && Vector3.Distance (transform.position, tilesTo$$anonymous$$ove [y].transform.position) != 0) {
 
                     transform.position = tilesTo$$anonymous$$ove [y].transform.position;
 
                 } else {
                 
                     transform.position += (tilesTo$$anonymous$$ove [y].transform.position - transform.position).normalized * speed;
                 
                 }
 
                 yield return new WaitForSeconds (0.01f);
 
             }
 
         }
 
         actionP -= tilesTo$$anonymous$$ove.Count;
         tilesTo$$anonymous$$ove.RemoveRange (0, tilesTo$$anonymous$$ove.Count);
 
     }

avatar image meat5000 ♦ · Jul 23, 2015 at 12:37 AM 0
Share

It contains a while loop inside a for loop (thats quadruple nested inside a for loop of undefined size thats double nested).

Its relevant :P

Have you worked out how long each branch takes to execute?

avatar image meat5000 ♦ · Jul 23, 2015 at 12:43 AM 0
Share

What happens if after the yield numOfTiles > actionP or any of the other conditions to get to the coroutine fails? $$anonymous$$ove2 would never return, would it?

2 Replies

  • Sort: 
avatar image
1
Best Answer

Answer by Bunny83 · Jul 23, 2015 at 08:14 AM

When your path is calculated and you start "StartCoroutine(Move2());" shouldn't you abort your Move method? A "break" or "return" would be appropriate once you started the coroutine. Keep in mind since you use a recursive approach once you exit the innermost "Move" method you get back to the point where you called that one in line 36. Since you're done with your path calculation you should make sure that all Move methods exit as soon as possible.

edit
Furthermore there are several things strange about your approach:

  • You use Physics.OverlapSphere which will include your current tile as well. You did not add the current tile to the checked list and didn't exclude it from the neighbors list as well. Since you call "Move" again for every "neighbor" you check the first tile twice.

  • Using OverlapSphere for every step in your pathfinding is very inefficient. You should store the immediate neighbor list inside your "TileProps" class. This information is usually static. You only need to set it up once at start of the game.

  • Unlike algorithms like "A*" you seem to search randomly for a path. You have alot strange abort conditions like one of your finish conditions is that the checkedtile count == the count of all available tiles.

  • Btw: There is "List.Clear()" ^^

  • Once your checkedTiles count hits the available tile count you clear the checkedTiles list, either start the actual moving or not but you continoue searching once you started Move2. Since you cleared the checkedTiles list every tile can be checked again. This will most likely continoue forever.

To sum this up: It's quite a mess ^^. Recursive approaches are dangerous and you easily loose track of the chain of execution. Even "A*" is usually implemented with a sorted queue. That doesn't prevent an infinite loop, but it's more obvious what the algorithm does and when it terminates (or not).

Keep in mind that you can use MonoDevelop to debug your Unity application. You can set breakpoints and step through your method and inspect the variables to see where it goes wrong.

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 Vini7x · Jul 23, 2015 at 08:29 PM 0
Share

Well, guess I will try to implement A* then, thanks for the help.

avatar image
1

Answer by PAHeartBeat · Jul 23, 2015 at 10:33 AM

in lines 15-25 i think you need to run reverce for loop to remove elements from list. so it will populate correct list in case any item removed from the list. it should be like that

      for(int i = neighbors.Count-1,i>=0; i--){
          Debug.Log(neighbors[i].name);
          if(!neighbors[i].GetComponent<TileProps>().walkable || neighbors[i].GetComponent<TileProps>().occupied || checkedTiles.Contains(neighbors[i])){
              neighbors.Remove(neighbors[i]);
          }
      }

Secondly if you tring to use a* path finding style for your game you need to check these link https://tbswithunity3d.wordpress.com/2012/02/23/hexagonal-grid-path-finding-using-a-algorithm/ http://ledpup.blogspot.in/2011/06/unity-hexagons-and-path-finding.html

these links about a* path finding in hex grid but you can also use it nomral square grid via little bit change Tile Class. Note: this scripts are not optimized or follw ART runtime. if you need to use your code iOS device you also need to remove uses of genrics and use specfic type in method FindPath of Path Class and Enqueue, Dequeue methods from PriorityQueue Class

Happy coding bro,

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

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

How to reach 2D Grid from script? How to reach every tilemap location and use them for pathfinding? 1 Answer

If Terrain is larger(width10000Xlength10000) then how to increase the size of the GridGraph of Astar Path Finder 0 Answers

Find a path with specific steps (moves) on a grid 0 Answers

TILE MOVEMENT 0 Answers

How can I get my pathfinding algorithm to know that it cant go through certain sides of tiles 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