Flexible A* Pathfinding System
by Dan Keller · 04/08/2008 (2:15 pm) · 203 comments
1.8.1 version here!
Download
Note: The TGEA version in the download is newer than the TGE version. Most people are using TGEA now, anyways. If you want the newer version in TGE, you can port it yourself, it shouldn't be too bad. If there is some interest in it and someone does a port, just send it to me and I'll put it up here.
Installation - TGEA
Add aStar.h, aStar.cpp, aStarIO.cpp, and aStarMesh.cpp to your project (in T3D). Replace or merge aiPlayer.cpp and .h with the files in in the zip.
Add #include "T3D/aStar.h" on top of sceneState.cpp
Add the commented part in SceneState::renderCurrentImages():
Add this in game/tools/missionEditor/scripts/editors/creator.ed.cs line 146:
Add the following function at the end of game/tools/missionEditor/gui/objectBuilderGui.ed.gui:
In [game]/scriptsAndAssets/server/scripts/game.cs, at the end of startGame(), add
At the end of endGame(), add
before resetMission();
For an example, add aiDemo.mis.
Installation - TGE
Add the aStar.cc and aStar.h files to your project. Replace or merge aiPlayer.cc and .h with the files in in the zip.
In sceneState.cc, after the includes, add
in renderCurrentImages(), around line 481, add the commented code
Save and compile.
In creator/editor/EditorGui.cs, at line 1306, change
to
In creator/editor/objectBuilderGui.gui, at line 643, add
In [game]/server/scripts/game.cs, at the end of startGame(), add
At the end of endGame(), add
before resetMission();
For an example, add aiDemo.mis.
Use
To add navigation points, open the mission editor creator. NavMesh objects are under Mission Objects / Mission. The properties are:
Interval - distance between points
XSize - number of points in x direction
YSize - number of points in y direction
Height - how far up or down the object will look to place points
There are two global preferences you can change. One is $Pref::AStar::Render. It controls whether or not the navigation mesh is rendered. Turn it on when editing the mesh, turn it off otherwise. The other is $Pref::AStar::Clearence. This controls the minimum horizontal clearance between two nodes when building paths. If you change this after creating points, you need to call buildPaths for it to effect those points.
There are three functions for path caching. Do not call any of these while the mission editor is running, it may get all messed up. They are
- deletePaths Deletes all NavMesh objects and all nodes.
- writePaths Writes all nodes to a file (called [mission name].as) that is loaded automatically on mission startup. This is the only function you need to call manually; call it once you're done editing the nav mesh.
- readPaths Reads nodes from file. Returns true on success, false on faliure.
Also there is
- buildPaths Manually rebuilds navigation information, for example if an object has been moved in the way of some nodes.
There is also a compiler switch, AI_RENDER, at the top of aStar.h. Comment this out when you distribute the game to remove all the nav mesh rendering code.
There are five functions that can be called on the AIPlayer object. They will return 0 on success, -1 on failure, and 1 if the bot is already where you want it to go. They are
- findPathTo This takes either a point or an object as an argument, and simply finds a way to the point.
- findCoverFrom This also takes a point or object, and finds a place hidden from it.
- searchCover This takes no arguments, and makes the bot go to the nearest place it can't see.
- sneakUpOn This takes either a point and a vector or an object as an argument. It finds a path to the point or the object that can't be seen by it.
- wander This takes a distance as an argument and wanders around for this distance.
Download
Note: The TGEA version in the download is newer than the TGE version. Most people are using TGEA now, anyways. If you want the newer version in TGE, you can port it yourself, it shouldn't be too bad. If there is some interest in it and someone does a port, just send it to me and I'll put it up here.
Installation - TGEA
Add aStar.h, aStar.cpp, aStarIO.cpp, and aStarMesh.cpp to your project (in T3D). Replace or merge aiPlayer.cpp and .h with the files in in the zip.
Add #include "T3D/aStar.h" on top of sceneState.cpp
Add the commented part in SceneState::renderCurrentImages():
PROFILE_START(RenderInstManagerRender); gRenderInstManager.render(); PROFILE_END(); //aStar #ifdef AI_RENDER AStar::Get()->render(this); #endif //aStar gRenderInstManager.clear(); mInteriorList.clear();
Add this in game/tools/missionEditor/scripts/editors/creator.ed.cs line 146:
%Mission_Item[6] = "NavMesh";
Add the following function at the end of game/tools/missionEditor/gui/objectBuilderGui.ed.gui:
function ObjectBuilderGui::buildNavMesh(%this)
{
%this.className = "NavMesh";
%this.process();
}In [game]/scriptsAndAssets/server/scripts/game.cs, at the end of startGame(), add
readPaths();
At the end of endGame(), add
deletePaths();
before resetMission();
For an example, add aiDemo.mis.
Installation - TGE
Add the aStar.cc and aStar.h files to your project. Replace or merge aiPlayer.cc and .h with the files in in the zip.
In sceneState.cc, after the includes, add
#include "game/aStar.h"
in renderCurrentImages(), around line 481, add the commented code
for (i = 0; i < mTranslucentEndImages.size(); i++)
renderImage(this, mTranslucentEndImages[i]);
//aStar
#ifdef AI_RENDER
gAStar.render(this);
#endif
//aStar
glMatrixMode(GL_MODELVIEW);
glPopMatrix();Save and compile.
In creator/editor/EditorGui.cs, at line 1306, change
%Mission_Item[3] = "Trigger"; %Mission_Item[4] = "PhysicalZone"; %Mission_Item[5] = "Camera";
to
%Mission_Item[3] = "NavMesh"; %Mission_Item[4] = "Trigger"; %Mission_Item[5] = "PhysicalZone"; %Mission_Item[6] = "Camera";
In creator/editor/objectBuilderGui.gui, at line 643, add
function ObjectBuilderGui::buildNavMesh(%this)
{
%this.className = "NavMesh";
%this.process();
}In [game]/server/scripts/game.cs, at the end of startGame(), add
readPaths();
At the end of endGame(), add
deletePaths();
before resetMission();
For an example, add aiDemo.mis.
Use
To add navigation points, open the mission editor creator. NavMesh objects are under Mission Objects / Mission. The properties are:
Interval - distance between points
XSize - number of points in x direction
YSize - number of points in y direction
Height - how far up or down the object will look to place points
There are two global preferences you can change. One is $Pref::AStar::Render. It controls whether or not the navigation mesh is rendered. Turn it on when editing the mesh, turn it off otherwise. The other is $Pref::AStar::Clearence. This controls the minimum horizontal clearance between two nodes when building paths. If you change this after creating points, you need to call buildPaths for it to effect those points.
There are three functions for path caching. Do not call any of these while the mission editor is running, it may get all messed up. They are
- deletePaths Deletes all NavMesh objects and all nodes.
- writePaths Writes all nodes to a file (called [mission name].as) that is loaded automatically on mission startup. This is the only function you need to call manually; call it once you're done editing the nav mesh.
- readPaths Reads nodes from file. Returns true on success, false on faliure.
Also there is
- buildPaths Manually rebuilds navigation information, for example if an object has been moved in the way of some nodes.
There is also a compiler switch, AI_RENDER, at the top of aStar.h. Comment this out when you distribute the game to remove all the nav mesh rendering code.
There are five functions that can be called on the AIPlayer object. They will return 0 on success, -1 on failure, and 1 if the bot is already where you want it to go. They are
- findPathTo This takes either a point or an object as an argument, and simply finds a way to the point.
- findCoverFrom This also takes a point or object, and finds a place hidden from it.
- searchCover This takes no arguments, and makes the bot go to the nearest place it can't see.
- sneakUpOn This takes either a point and a vector or an object as an argument. It finds a path to the point or the object that can't be seen by it.
- wander This takes a distance as an argument and wanders around for this distance.
About the author
#162
11/15/2009 (3:48 pm)
This is a fantastic resource. I was wondering - how hard would it be to allow a new obstacle to be inserted into the mesh and to have only the part of the mesh around that obstacle regenerated?
#163
Then you'll want to create another version of the buildPaths ConsoleFunction that takes editPt and editDst as arguments.
11/15/2009 (3:58 pm)
It wouldn't be too hard- basically you'd want another version of the linkMeshes function in aStar.cpp with a bit of code afterfor (cur = list; cur; cur = cur->next)
{that's something likeif ((cur->pos - editPt).len() > editDst)
continue;where editPt is where the obstacle is and editDst is how big it is.Then you'll want to create another version of the buildPaths ConsoleFunction that takes editPt and editDst as arguments.
#164
Also whats the best strategy for really huge terrains and this resource. I have 2 problems. buildPaths take a really long time when i cover the whole map with one grid and the rendering of the lines kills my pc('s performance).
11/17/2009 (7:47 am)
Has anyone gotten the default torque vehicles to use this method of path finding? I tried dropping the Boom Bot into the starter buggy and he just drove off to little clearing and started driving around in circles.Also whats the best strategy for really huge terrains and this resource. I have 2 problems. buildPaths take a really long time when i cover the whole map with one grid and the rendering of the lines kills my pc('s performance).
#165
11/17/2009 (12:57 pm)
Hi Adam, the T3D resource download link is no longer working. Can you fix?
#166
11/19/2009 (3:32 pm)
If you have the new version, use the codeAStar::Get()->render(this);But i can't guarantee that render() itself will work, because I don't have T3D.
#167
i try 1.8.1 version but compile have a error about
"fatal error C1083: Cannot open include file: 'T3D/aiManager.h': No such file or directory"
i check astar.h have change #include "T3D/aiManager.h"
so i search my TGEA_1_8_1 folder but cant see "aiManager.h" the file...
how am i get the aiManager.h file??
thx a lot ur help~
11/24/2009 (10:19 am)
hi dan i try 1.8.1 version but compile have a error about
"fatal error C1083: Cannot open include file: 'T3D/aiManager.h': No such file or directory"
i check astar.h have change #include "T3D/aiManager.h"
so i search my TGEA_1_8_1 folder but cant see "aiManager.h" the file...
how am i get the aiManager.h file??
thx a lot ur help~
#168
You'd need to get a license for the source code, which would provide the file, since you don't seem to have one.
11/24/2009 (10:33 am)
Quote:how am i get the aiManager.h file??
You'd need to get a license for the source code, which would provide the file, since you don't seem to have one.
#169
11/24/2009 (5:07 pm)
Whoops, just comment out the #include for that, it wasn't supposed to be there.
#170
Also, if anyone is interested, I have the following script used for NPCs to wander from one building to another. The buildings are, in this case, grouped into a Simset named Tents, and I just pick one at random and the NPC walks to it. Figure it's probably nice for a market scene (which is what I'm using it for):
11/30/2009 (12:54 am)
Awesome resource! Much better than the hapless wander functions I had scripted :)Also, if anyone is interested, I have the following script used for NPCs to wander from one building to another. The buildings are, in this case, grouped into a Simset named Tents, and I just pick one at random and the NPC walks to it. Figure it's probably nice for a market scene (which is what I'm using it for):
function AIPlayer::bldgWander(%this)
{
//Select a building and get its position
%i = randInRange(0, Tents.getCount()-1); //Replace this with a rand function of your choice...
%pos = Tents.getObject(%i).getPosition();
%this.setAimLocation(%pos);
%this.findPathTo(%pos);
}
#171
I had to copy the disStr function from the TGE version of the code and add the filestream header to even get it to compile.
In game it crashes without warning when trying to use wander, and when i try to enable the rendering i get all kinds of errors and warnings when compiling.
so again, if anybody has a version that works in stock 1.8.1 could you please post it?
12/18/2009 (1:13 pm)
I'm using 1.8.1 and tne original resource is missing half of its own code, if anybody has a version that drops right into 1.8.1 can you post the files somewhere because the original resource download doesnt.I had to copy the disStr function from the TGE version of the code and add the filestream header to even get it to compile.
In game it crashes without warning when trying to use wander, and when i try to enable the rendering i get all kinds of errors and warnings when compiling.
so again, if anybody has a version that works in stock 1.8.1 could you please post it?
#172
Any clue when that part in findPoint would actually be used to find a point that isn't matched in the first loop. I want to use this code in conjuction with our old path finding code since it is a bit more stupid and better suited for an MMO when there is no path finding needed (point A marker is clear to point B maker). If you try to plot a point that isn't in the mesh that 2nd bit of code really kills you. I took it out and haven't seen a lot of problems yet.
01/08/2010 (8:32 pm)
Implemented this into our T3D build after a bit of changes here and there it seems to be working without issue. I do have a question about 1 segment of code though in aStarMesh.cppsortPoints(pt);
for (int i=0; i<sortVec.size(); i++)
if (disSqr(sortVec[i]->loc, pt) > LOOK_DIS_SQR && !gServerContainer.castRay(sortVec[i]->loc, pt, ( InteriorObjectType | StaticTSObjectType | StaticShapeObjectType ), &rInfo))
return sortVec[i];Any clue when that part in findPoint would actually be used to find a point that isn't matched in the first loop. I want to use this code in conjuction with our old path finding code since it is a bit more stupid and better suited for an MMO when there is no path finding needed (point A marker is clear to point B maker). If you try to plot a point that isn't in the mesh that 2nd bit of code really kills you. I took it out and haven't seen a lot of problems yet.
#173
01/08/2010 (9:12 pm)
The purpose of this code is to find reachable points farther away than sqrt(LOOK_DIS_SQR), if there are no reachable points closer. It won't hurt to comment it out, because it will just reject points too far away from a mesh. It was intended as a last resort to find a point before just giving up.
#174
01/09/2010 (7:28 pm)
Thanks Dan. For the most part it will typically be close distance checks so I think I will be safe without that. Would be nice to find a cleaner way to search the mesh list as well as it looks like it is just doing a brute search through all of the points in the list looking for something. Only testing with a small mesh, I would imagine one with 100,000 or more points to search through would be a bit hungry.
#175
may i ask a question?
i see aiDemo.mis.
but when i create a AIplayer in navigation mesh,
how i use findPathTo the functions??
press ~ use
findPathTo NPCname?? or findPathTo location??
but i try always "<input> (0): Unable to find function findPathTo"
no see anyone move~
can u tell me how do it??
i really very need the functions!
thx a lots and please~
01/17/2010 (6:34 pm)
hi dan~may i ask a question?
i see aiDemo.mis.
but when i create a AIplayer in navigation mesh,
how i use findPathTo the functions??
press ~ use
findPathTo NPCname?? or findPathTo location??
but i try always "<input> (0): Unable to find function findPathTo"
no see anyone move~
can u tell me how do it??
i really very need the functions!
thx a lots and please~
#176
01/18/2010 (5:19 pm)
findPathTo runs in the bot's object namespace. So if the aiplayer object is stored in %bot, you call %bot.findPathTo(location). If you want to find a path to a player object, you would call %bot.findPathTo(%player.getPosition())
#177
I'm very interested in getting this to work in T3D 1.0 I'm getting errors no matter what I do. Do you still have your working files?
02/12/2010 (7:04 pm)
Hey deepscratchI'm very interested in getting this to work in T3D 1.0 I'm getting errors no matter what I do. Do you still have your working files?
#178
Error 1 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStar.cpp 256
Error 2 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStar.cpp 257
Error 3 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStar.cpp 257
Error 4 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStarMesh.cpp 378
Error 5 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStarMesh.cpp 379
Error 6 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStarMesh.cpp 399
Error 7 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStarMesh.cpp 400
Error 8 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStarMesh.cpp 400
Error 9 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStarMesh.cpp 415
Error 10 error C2065: 'gAStar' : undeclared identifier c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourcesceneGraphsceneState.cpp 161
Error 11 error C2228: left of '.render' must have class/struct/union c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourcesceneGraphsceneState.cpp 161
Error 12 fatal error C1083: Cannot open include file: 'T3D/moveManager.h': No such file or directory c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaiPlayer.cpp 8
Error 13 error BK1506 : cannot open file '....LinkVC2k8.Release.Win32test DLLaiPlayer.sbr': No such file or directory BSCMAKE
Error 14 fatal error LNK1181: cannot open input file '......gametest.lib' test
Error 15 fatal error LNK1181: cannot open input file '......gametest.lib' NP test Plugin
Error 16 fatal error C1083: Cannot open include file: 'atlbase.h': No such file or directory c:torquetorque 3d 2009 pro 1.1 beta 1my projectstestwebsourceactivexstdafx.h 19
I can diagnose the problem but I don't know how to fix it (i.e. if there are lines that need to be changed, I don't know what to change them to). I read people have implemented this into T3D before but I don't see how if there are so many errors if possible can some one who has implemented this into T3D help me please.
02/19/2010 (11:02 am)
Hi I am trying to implement this into T3D 1.1 BETA but I can't get past the C++ stuff because I keep getting a crap load of errors. I have managed to fix some but there are still more. Here they areError 1 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStar.cpp 256
Error 2 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStar.cpp 257
Error 3 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStar.cpp 257
Error 4 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStarMesh.cpp 378
Error 5 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStarMesh.cpp 379
Error 6 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStarMesh.cpp 399
Error 7 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStarMesh.cpp 400
Error 8 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStarMesh.cpp 400
Error 9 error C3861: 'disSqr': identifier not found c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaStarMesh.cpp 415
Error 10 error C2065: 'gAStar' : undeclared identifier c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourcesceneGraphsceneState.cpp 161
Error 11 error C2228: left of '.render' must have class/struct/union c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourcesceneGraphsceneState.cpp 161
Error 12 fatal error C1083: Cannot open include file: 'T3D/moveManager.h': No such file or directory c:TorqueTorque 3D 2009 Pro 1.1 Beta 1EnginesourceT3DaiPlayer.cpp 8
Error 13 error BK1506 : cannot open file '....LinkVC2k8.Release.Win32test DLLaiPlayer.sbr': No such file or directory BSCMAKE
Error 14 fatal error LNK1181: cannot open input file '......gametest.lib' test
Error 15 fatal error LNK1181: cannot open input file '......gametest.lib' NP test Plugin
Error 16 fatal error C1083: Cannot open include file: 'atlbase.h': No such file or directory c:torquetorque 3d 2009 pro 1.1 beta 1my projectstestwebsourceactivexstdafx.h 19
I can diagnose the problem but I don't know how to fix it (i.e. if there are lines that need to be changed, I don't know what to change them to). I read people have implemented this into T3D before but I don't see how if there are so many errors if possible can some one who has implemented this into T3D help me please.
#179
The gAstar problem is fixed by using the TGEA instructions instead of the TGE ones.
As for moveManager.h, it may be somewhere else in T3D, or it may have been taken out. Try commenting out the line, and if that doesn't work, hunt around.
02/25/2010 (12:16 pm)
Ok you have three problems here. To fix the disSqr thing, add these lines at around 154 in aStar.hinline F32 disSqr(Point3F a, Point3F b)
{
return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) + (a.z-b.z)*(a.z-b.z);
}The gAstar problem is fixed by using the TGEA instructions instead of the TGE ones.
As for moveManager.h, it may be somewhere else in T3D, or it may have been taken out. Try commenting out the line, and if that doesn't work, hunt around.
#180
05/19/2010 (12:41 pm)
This is the best resource yet it is great thanks a heap 
Torque 3D Owner Dan Keller
Default Studio Name