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 DayyanSisson · Dec 11, 2012 at 03:06 AM · pathfindingpathtargetnodes

Pathfinding help

I've created a fairly simple A* Pathfinding script, but I have encountered one problem. The pathfinder will try and take the shortest path, only to find that there's a one node gap between it and the target node and it keeps doubling back on itself. So it'll move up right next to the target node, but all the nodes leading around the pathfinder are all blocked (including the one in-between the pathfinder and the target node) and the only way out is the way it came. But as soon as it moves back the way it came, it tries to re-do what it just did, and then creates this loop where it just moves back & forth. I have no idea how to avoid this. What should I do?

Here's some of the code if it'll help you understand:

 void CheckNode () {
 
         float lowestF = Mathf.Infinity;
         Transform nextNode = null;
 
         int a = 0;
         while(a < open.Count){
             List<Transform> thisOpen = FindAdjacentNodes(open[a]);
             bool addWeight = false;
             float weight = 0;
             foreach(Transform n in thisOpen){
                 if(!open.Contains(n) && !addWeight){
                     addWeight = false;
                     weight = 0;
                 }else{
                     addWeight = true;
                     weight = errorWeight;
                 }
             }
             if((((current.position - open[a].position).magnitude + (finish.position - open[a].position).magnitude) + weight) < lowestF){
                 nextNode = open[a];
                 lowestF = (current.position - open[a].position).magnitude + (finish.position - open[a].position).magnitude;
             }
             a++;
         }
 
         if(!closed.Contains(current)){
             closed.Add(current);
         }
         current = nextNode;
         if(!closed.Contains(current)){
             closed.Add(current);
         }
         lastOpen = open;
         open = FindAdjacentNodes(current);
         if(current){
             int b = 0;
             while(b < nodes.Count){
                 int c = 0;
                 while(c < nodes[b].nodeVectors.Count){
                     foreach(Transform n in lastOpen){
                         if(n == nodes[b].nodeVectors[c]){
                             nodes[b].nodeVectors.Remove(nodes[b].nodeVectors[c]);
                         }
                     }
                     c++;
                 }
                 b++;
             }
             closed.Clear();
             open.Clear();
             closed.Add(start);
             current = start;
         }
         current.renderer.material = green;
     }

EDIT

So the above problem has been solved, but the pathfinding itself still gives me a weird path. I started this thread here if maybe you could help me out.

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

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by FlowStateGames · Dec 11, 2012 at 02:09 PM

First of all, I would encourage you to look into theta-star pathing, as it's not any more complicated than A*, is more efficient, etc. For your particular problem, it would be really nice to see more information, but I think I get the gist of the issue.

Okay, so basically you have two similar options for a solution to this:

  • Give your pathing system "lookahead" to pre-evaluate the next-node solution.

  • Give your system a "history" or move-buffer so that 'mistakes' won't be repeated.

From experience, I'd say that the first solution is preferable. There are two general ways to achieve this:

  • Naive lookahead: basically, your lookahead can only return a bool "pathNotValid". As you can guess, this will mean "if I move here, I'll have to move back". This is easy to evaluate, but relatively short on information.

  • Weighted lookahead: this method is a little more expensive, but returns much more information. Essentially, you buffer a full round of node evaluation for the prospective node you're going to move to. The only real difference is that you can apply some insane weight to the node you're currently on. This way, your algorithm can stay the same, because you'll be evaluating on weight; you're simply heavily-punishing backtracking.

To sum up, when you're evaluating the possible next nodes, queue them up with the most-desirable first, then do a lookahead to evaluate the next move from that node. Pass into this lookahead method the id of your current node, so that you can heavily weight backtracking.

EDIT: You are going to hate me for this, but I've done it before (not in Unity, sadly) and it is an amazing tool to have. What I would suggest is the following:

Tie the nodes to GameObjects which can be manually or procedurally placed in your scene.

Your goal is to be able to step through the pathfinding steps, and color the nodes each step to reflect their state in the algorithm (neighbor, current node, etc). This way you can create different scenarios in which to test your algorithm.

The more robust solution would be to indicate path weight visually. The two ways to do this would be to either float text above each node, or to use the color value of the material to denote weight (start at 255,255,255 then make the material darker and darker if it's a heavy path).

It's 3am, I hope this makes sense. If not, I'll rewrite in the morning.

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 DayyanSisson · Dec 14, 2012 at 04:59 AM 0
Share

So I tried the lookahead approach and wasn't able to get it to work. Basically what I did was check the node in front of it and check to see if there were any adjacent nodes besides the ones already on the open list. If there is, move on as normal, if not, I skipped that node. I tried doing that and I got weird effects; it started creating a weird path that ended up ter$$anonymous$$ating itself. I also tried just adding a weight to that node, and it moved in the right direction, but it ter$$anonymous$$ated too. Not sure if I understood you right.

avatar image DayyanSisson · Dec 15, 2012 at 07:40 PM 0
Share

This code adds the weight:

 List thisOpen = FindAdjacentNodes(open[a]);
                 bool addWeight = false;
                 float weight = 0;
                 foreach(Transform n in thisOpen){
                     if(!open.Contains(n) && !addWeight){
                         addWeight = false;
                         weight = 0;
                     }else{
                         addWeight = true;
                         weight = errorWeight;
                     }
                 }

This code attempts to restart the search if original path doesn't work:

 lastOpen = open;
         open = FindAdjacentNodes(current);
         if(open.Count < 1){
             int b = 0;
             while(b < nodes.Count){
                 int c = 0;
                 while(c < nodes[b].nodeVectors.Count){
                     foreach(Transform n in lastOpen){
                         if(n == nodes[b].nodeVectors[c]){
                             nodes[b].nodeVectors.Remove(nodes[b].nodeVectors[c]);
                         }
                     }
                     c++;
                 }
                 b++;
             }
             closed.Clear();
             open.Clear();
             closed.Add(start);
             current = start;
             open = FindAdjacentNodes(current);
         }

Just a little bit more information if it'll help you understand.

avatar image FlowStateGames · Dec 18, 2012 at 05:36 PM 0
Share

Please see my edit above, let me know if it makes sense to you.

avatar image DayyanSisson · Dec 22, 2012 at 07:05 AM 0
Share

Yup, thats more or less what I've done, to check how its been going.

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

11 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

Related Questions

iTween, moving to a node on a path. 1 Answer

A* pathfinding, Re checking nodes 1 Answer

A* Pathfinding, destroying a path once it has reached its end 0 Answers

Aron Ganberg Astar - add nodes at runtime with pointgraph 0 Answers

Is it possible to store NavMeshAgents paths and assign them to other NavMeshAgents later? 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