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
#142
10/08/2009 (10:37 pm)
-please delete me-
#143
10/08/2009 (10:40 pm)
-please delete me-
#144
www.ignitiongamespm.com/uploads/Adam/aStar.rar
10/08/2009 (11:36 pm)
Heres a working T3D 1.0 version of the A* source:www.ignitiongamespm.com/uploads/Adam/aStar.rar
#145
10/08/2009 (11:45 pm)
-please delete me-
#146
10/09/2009 (4:34 am)
-please delete me-
#147
How do I stop the AI from twitching? they are following the paths nicely but a little too closely and it is making them slow down and turn to the node every so often.
This make the animation restart and the movements look jerky and unnatural.
Thanks in advance :)
-so sorry, I feel like gg #1 troll :P-
10/10/2009 (10:11 am)
-pains me to make yet another comment on this great resource-How do I stop the AI from twitching? they are following the paths nicely but a little too closely and it is making them slow down and turn to the node every so often.
This make the animation restart and the movements look jerky and unnatural.
Thanks in advance :)
-so sorry, I feel like gg #1 troll :P-
#148
10/10/2009 (11:42 am)
You can increase $Pref::AStar::Clearence a bit.
#149
10/10/2009 (7:45 pm)
What values would you recommend? none of them seem to be doing anything.
#150
The other option is to slow down your bots.
10/10/2009 (11:38 pm)
I dunno, between 0.5 and 1.5 maybe.The other option is to slow down your bots.
#151
EDIT: Also, how can I make a function pause while the AI is walking to a position? Here is a function I was just writing and i need to make it wait before completing the rest of the command.
10/11/2009 (1:48 am)
Well I'll try, the problem is that my bots are very slow and they still have trouble. Here is a video of the bots wandering, with clearence set to 1.2.EDIT: Also, how can I make a function pause while the AI is walking to a position? Here is a function I was just writing and i need to make it wait before completing the rest of the command.
function AIPlayer::tavernActivities(%this)
{
// Generate a random activity
%activity = getTavernActivity();
// Do the activity
switch$(%activity){
case "drinking":
// drinking here
case "talking":
%this.findPathTo(talking);
// WAIT FOR AI TO REACH DESTINATION
%this.startTalking();
case "dancing":
// dancing here
}
}
#152
I forgot to mention, for clearance to take effect, you have to call buildPaths() after changing it.
10/11/2009 (12:29 pm)
You can use the onReachDestination callback to detect when a path has been completed, and have a "state" variable in the aiplayer object that keeps track of what it's going to do.I forgot to mention, for clearance to take effect, you have to call buildPaths() after changing it.
#153
Thanks for callback help btw
edit: is this code supposed to be what I have for the callback function?
10/11/2009 (11:14 pm)
This isn't being fixed with the $pref::astar::clearence value, i went from 0.5 - 25 and then decided it was another problem.Thanks for callback help btw
edit: is this code supposed to be what I have for the callback function?
function AIPlayer::onReachDestination(%this);
#154
Clearance, by the way, is used in the "walkability" calculations, but only when connecting nodes. Try setting $Pref::AStar::Render to 1, and increasing the clearance alternately with calling buildpaths(). Some paths, the ones near walls or columns, should disappear. If you can set it to 25 with no effect, I'm not sure what the problem could be.
10/12/2009 (10:28 am)
No, ai callbacks happen in the datablock namespace, so it should bePlayerData::onReachDestination(%this,%obj)
{
//...
}Clearance, by the way, is used in the "walkability" calculations, but only when connecting nodes. Try setting $Pref::AStar::Render to 1, and increasing the clearance alternately with calling buildpaths(). Some paths, the ones near walls or columns, should disappear. If you can set it to 25 with no effect, I'm not sure what the problem could be.
#155
10/12/2009 (10:46 am)
Is there a way to set a radius around each node that would make it count as being completed, so they don't have to be so exact? My problem isn't so much that they get stuck on things, but rather that they stop and start many times a second as they line themselves up. In that video I gave you, the AI walks like that no matter where they are. Its the same up a steep hill and on a flat area, in and out of buildings.
#156
aiPlayer.cpp, around line 256, is
The code is responsible for smoothing out mostly-straight sections of path (tol is the acceptable distance to the node to consider it "reached"), but I apparently got the dot product backwards in my mind. Oops.
10/12/2009 (12:20 pm)
It uses clearance for that, too, but I just realized there is a bug in the codeaiPlayer.cpp, around line 256, is
if (path.size() > 2 && !gServerContainer.castRay(location, path[2], STATIC_COLLISION_MASK, &rInfo))
{
Point3F a(path[0]-path[1]);
Point3F b(path[1]-path[2]);
a.normalize();
b.normalize();
tol = 2 - mDot(a, b);
tol *= gAStar.clearence;
}
else
tol = gAStar.clearence;but should beif (path.size() > 2 && !gServerContainer.castRay(location, path[2], STATIC_COLLISION_MASK, &rInfo))
{
Point3F a(path[0]-path[1]);
Point3F b(path[1]-path[2]);
a.normalize();
b.normalize();
tol = 1 + mDot(a, b);
tol *= gAStar.clearence;
}
else
tol = gAStar.clearence;The code is responsible for smoothing out mostly-straight sections of path (tol is the acceptable distance to the node to consider it "reached"), but I apparently got the dot product backwards in my mind. Oops.
#157
10/12/2009 (8:11 pm)
I added the change and it's a little better, but still not the way I would like it. They are still jerky. Could I maybe share the source code I am using with you? Perhaps I broke something while getting it to work in T3D.
#158
Add this in game/tools/missionEditor/scripts/editors/creator.ed.cs line 146:
view plainprint?
1. %Mission_Item[6] = "NavMesh";
%Mission_Item[6] = "NavMesh";
<-There is no Mission_Item anymore it seems ? where does this code goes ?
Add the following function at the end of game/tools/missionEditor/gui/objectBuilderGui.ed.gui:
view plainprint?
1. function ObjectBuilderGui::buildNavMesh(%this)
2. {
3. %this.className = "NavMesh";
4. %this.process();
5. }
function ObjectBuilderGui::buildNavMesh(%this)
{
%this.className = "NavMesh";
%this.process();
}
This i copied to the relevant folder but i used the world editor sub folder am i wrong ?
10/30/2009 (7:11 pm)
Can somebody explained how they made it to show up in T3d the following seems to be harder for me to implement than code since i am unfamilar with the different editor functionnalites and the code documentation is inexistant on how to expand :Add this in game/tools/missionEditor/scripts/editors/creator.ed.cs line 146:
view plainprint?
1. %Mission_Item[6] = "NavMesh";
%Mission_Item[6] = "NavMesh";
<-There is no Mission_Item anymore it seems ? where does this code goes ?
Add the following function at the end of game/tools/missionEditor/gui/objectBuilderGui.ed.gui:
view plainprint?
1. function ObjectBuilderGui::buildNavMesh(%this)
2. {
3. %this.className = "NavMesh";
4. %this.process();
5. }
function ObjectBuilderGui::buildNavMesh(%this)
{
%this.className = "NavMesh";
%this.process();
}
This i copied to the relevant folder but i used the world editor sub folder am i wrong ?
#159
10/30/2009 (7:27 pm)
ok forget the last comment it seems i got it right, i did not know though i had to actually run the compiled code, i thought that maybe the toolbox would actually start the compiled editor if it existed... my fault.
#160
have anyone can teaching me how to spwan a aiplayer?
can build navmesh but cant use bot to try...
i always got some question....
==>BuildPaths();
Built paths in 31 ms; 130 nodes.
==>bob.wander("1,1,1");
<input> (0): Unable to find object: 'bob' attempting to call function 'wander'
==>111.wander("1,1,1");
<input> (0): Unknown command wander.
Object CrossbowSubExplosion2(111) CrossbowSubExplosion2 -> ExplosionData -> GameBaseData -> SimDataBlock -> SimObject
and my version is 1.7.1
plz help~
thx a lots
11/14/2009 (6:40 am)
hello all have anyone can teaching me how to spwan a aiplayer?
can build navmesh but cant use bot to try...
i always got some question....
==>BuildPaths();
Built paths in 31 ms; 130 nodes.
==>bob.wander("1,1,1");
<input> (0): Unable to find object: 'bob' attempting to call function 'wander'
==>111.wander("1,1,1");
<input> (0): Unknown command wander.
Object CrossbowSubExplosion2(111) CrossbowSubExplosion2 -> ExplosionData -> GameBaseData -> SimDataBlock -> SimObject
and my version is 1.7.1
plz help~
thx a lots

Torque Owner BryceSquared
Default Studio Name
Sorry for taking up such a large part of the comments :(