Path finding
by Mike G · in Torque Game Engine · 07/29/2009 (5:38 am) · 13 replies
i have paths laied out for my npcs to walk. now how do i make them follow that? i saw the starter.fps thing and couldnt figure out how to implement this function.
About the author
#2
07/29/2009 (11:39 am)
Did you lay your paths out correctly?Quote:
There is an old "Bot Path-finding" tutorial, and other useful tutorials that are still relevant today found on the CodeSampler.com
But basically and since I've answered this question a dozen times:
For the paths to work correctly with the code that is in aiPlayer.cs you'll use the Mission Editor to place a series of numbered path markers that make up a path.
1: create a new SimGroup called "Paths" -- SimGroup(Paths) 2: inside this SimGroup you will place a "Path" object. Call it "Path1". 3: create a series of "PathMarkers" under the Path object, still inside the SimGroup. Place these "PathMarkers" where you want them.
Each PathMarker will need to have it's own "seqNum" field. This is the order in which the bot will follow the nodes(markers) on the path, 1 - 2 - 3 - 4 - etc, etc so on and so forth then back to marker #1 ad infinitum. All other fields are self-explanatory or should only take a little bit of experimentation to understand what they do/mean.
4: Save the mission. Reload.
If all steps are performed correctly you will then see a "dumb" bot following the path you just laid out.
#3
07/29/2009 (11:42 am)
Once you have the path created correctly, it is the code (AIManager) that starts the AIPlayer running around. You would want to modify the code in aiPlayer.cs in order to extend this functionality.
#4
07/29/2009 (12:47 pm)
but how do i make it apart of the path? i have the path markers layed out.
#5
The documentation should cover how to add/use SimGroups from within the editor. So long as your groups are named correctly then it will work.
07/29/2009 (1:51 pm)
Quote:
For the paths to work correctly with the code that is in aiPlayer.cs you'll use the Mission Editor to place a series of numbered path markers that make up a path.
1: create a new SimGroup called "Paths" -- SimGroup(Paths) 2: inside this SimGroup you will place a "Path" object. Call it "Path1". 3: create a series of "PathMarkers" under the Path object, still inside the SimGroup. Place these "PathMarkers" where you want them.
Each PathMarker will need to have it's own "seqNum" field. This is the order in which the bot will follow the nodes(markers) on the path, 1 - 2 - 3 - 4 - etc, etc so on and so forth then back to marker #1 ad infinitum. All other fields are self-explanatory or should only take a little bit of experimentation to understand what they do/mean.
4: Save the mission. Reload.
The documentation should cover how to add/use SimGroups from within the editor. So long as your groups are named correctly then it will work.
#6
AIManager runs automatically, right from the start. The only reason it (AIManager) doesn't create a bot for you is because it needs a proper path to do so. The moment you create a proper path, save and reload, then AIManager will use that path to spawn a bot on.
you don't have to "make it apart of the path" AIManager does that for you. All you have to do is, follow steps 1,2, 3, and 4 as Michael laid them out above, and you should see the bot running around. You have to understand that the name and paths he gave above are the only ones that work. You can't change the name or paths or AIManager won't find the path. (Well, you could change them, but then you would have to change some of the AIManager scripts). The correct names and directory structure of the path is the important thing. The physical layout of the markers is not very important.
07/29/2009 (1:52 pm)
Here is my understanding of it, which is basically a reiteration of what Michael said above:AIManager runs automatically, right from the start. The only reason it (AIManager) doesn't create a bot for you is because it needs a proper path to do so. The moment you create a proper path, save and reload, then AIManager will use that path to spawn a bot on.
you don't have to "make it apart of the path" AIManager does that for you. All you have to do is, follow steps 1,2, 3, and 4 as Michael laid them out above, and you should see the bot running around. You have to understand that the name and paths he gave above are the only ones that work. You can't change the name or paths or AIManager won't find the path. (Well, you could change them, but then you would have to change some of the AIManager scripts). The correct names and directory structure of the path is the important thing. The physical layout of the markers is not very important.
#7
Why are AIPlayer::spawn() and AIPlayer::spawnonpath() called "AI player static functions" in the comments? I have a basic understanding of a static function, but I don't understand how it applies here.
Is it possible to call aiplayer::spawn and aiplayer::spawnonpath() without the use of the AIManager? That is, If i comment out the section where AIManger is started, can I call these functions myself? I can not seem to get them to work. I have tried the following:
which didnt work. I then tried:
As well as a slew of other things. I can't figure out what I am doing wrong.
07/29/2009 (2:02 pm)
I, myself, have a couple related questions, which I hope do not hijack this thread. Now that I understand and have gotten the Bot to work using AIManager, I wonder: Why are AIPlayer::spawn() and AIPlayer::spawnonpath() called "AI player static functions" in the comments? I have a basic understanding of a static function, but I don't understand how it applies here.
Is it possible to call aiplayer::spawn and aiplayer::spawnonpath() without the use of the AIManager? That is, If i comment out the section where AIManger is started, can I call these functions myself? I can not seem to get them to work. I have tried the following:
$mynpc1 = new AiPlayer("portguard")
{
//dataBlock = DemoPlayer;
dataBlock = npcguard;
path = "";
};
$mynpc1.spawnOnPath("portguard","missiongroup/Paths/Path1"); which didnt work. I then tried:
%player = AIPlayer::spawnOnPath("Shootme", "MissionGroup/Paths/Path1");As well as a slew of other things. I can't figure out what I am doing wrong.
#8
Do your bots spawn but just stand there? Or do they not appear at all?
It's the AIManager that handles spawning, respawning, thinking. And by thinking, it simply tells the AIPlayer to check it's condition and methods to best decide what to do. It does this every 500 ms.
Without the AIManager then the AI has no way of "thinking" for itself. But this can be re-written... and that's a long involved topic in itself.
The Killer Korc and Improved Ai-guard resources are two script only resources that can greatly improve upon the basic AI. Both are great to learn from and lot's of fun to experiment with.
07/29/2009 (7:19 pm)
Well... by default the pathed AI requires the AIManager to be active for the AI to work. Do your bots spawn but just stand there? Or do they not appear at all?
It's the AIManager that handles spawning, respawning, thinking. And by thinking, it simply tells the AIPlayer to check it's condition and methods to best decide what to do. It does this every 500 ms.
Without the AIManager then the AI has no way of "thinking" for itself. But this can be re-written... and that's a long involved topic in itself.
The Killer Korc and Improved Ai-guard resources are two script only resources that can greatly improve upon the basic AI. Both are great to learn from and lot's of fun to experiment with.
#9
Someone might have been in a hurry when they wrote those comments and didn't really consider the implications of their words... who knows ;)
07/29/2009 (7:24 pm)
Never really thought about "why?" those are called static functions. Maybe because they don't do anything without the AIManager? No other class can/would call them?Someone might have been in a hurry when they wrote those comments and didn't really consider the implications of their words... who knows ;)
#10
find the bot, but I see it in the Tree() console function, so it must
exist, but it is certainly not anywhere near the path.
I understand that AIManager is designed to automatically call AIPlayer
functions. I also understand that should I get a bot to spawn without
AImanager it is up to me to add functionality.
The crux of my problem is this:
When AIManager::spawn() calls AIPlayer::spawnonPath() it passes 2
parameters: %name and %path. Specifically, in this case: "shootme"
and "missiongroup/paths/path1".
I put a watch in Torsion on those parameters and they are indeed
passed using the strings above.
AIPlayer::spawnonpath() checks to make sure the path is a valid object here:
if (!isObject(%path))
return 0;
else continue // not the exact code, but you get the point
When AIManger calls spawnonpath the path is valid and the function
continues.
However, when I use this syntax:
$mynpc1 = new AiPlayer()
{
dataBlock = DemoPlayer;
path = "";
};
$mynpc1=AIPlayer::spawnOnPath("shootme",
"missiongroup/Paths/Path1");
The path check in the if statement above fails.
I put a watch in torsion on the name and path parameters and they are
the same as the ones that AIManager passes!!!!!!!
This is blowing my mind. It has to be something I don't understand in
the way that I am calling the function.
How can "missiongroup/paths/path1" sometimes be a valid object and
sometimes not? I have not touched that at all!
07/30/2009 (10:32 am)
Well, for a long time, I thought that the bot did not spawn. I cannot find the bot, but I see it in the Tree() console function, so it must
exist, but it is certainly not anywhere near the path.
I understand that AIManager is designed to automatically call AIPlayer
functions. I also understand that should I get a bot to spawn without
AImanager it is up to me to add functionality.
The crux of my problem is this:
When AIManager::spawn() calls AIPlayer::spawnonPath() it passes 2
parameters: %name and %path. Specifically, in this case: "shootme"
and "missiongroup/paths/path1".
I put a watch in Torsion on those parameters and they are indeed
passed using the strings above.
AIPlayer::spawnonpath() checks to make sure the path is a valid object here:
if (!isObject(%path))
return 0;
else continue // not the exact code, but you get the point
When AIManger calls spawnonpath the path is valid and the function
continues.
However, when I use this syntax:
$mynpc1 = new AiPlayer()
{
dataBlock = DemoPlayer;
path = "";
};
$mynpc1=AIPlayer::spawnOnPath("shootme",
"missiongroup/Paths/Path1");
The path check in the if statement above fails.
I put a watch in torsion on the name and path parameters and they are
the same as the ones that AIManager passes!!!!!!!
This is blowing my mind. It has to be something I don't understand in
the way that I am calling the function.
How can "missiongroup/paths/path1" sometimes be a valid object and
sometimes not? I have not touched that at all!
#11
I added a one line function called spawnBot() from which I call AIPlayer::spawnOnPath() with both parameters, a name and a path. The bot does spawn and from there I can tell it to followPath() and it does so.
Of course I think it would make much more sense to do something like this
You could even go so far as to add another parameter in there that contains a datablock name for AIPlayer::spawn() to use, but that DBname would have to be passed from spawnBot() to AIPlayer::spawnOnPath() which in turn was modified to pass this extra parameter on to AIPlayer::spawn(). This would allow you to have different bot names, different paths, and different datablocks that bots would use, all called from the same reusable function but with different parameters.
07/30/2009 (10:29 pm)
Hmmm, I'm not really sure what's going on there. I can get it to work for me, even after disabling the AIManager. It seems that the AIManager doesn't actually do anything except handle spawning by default. I never noticed that before.I added a one line function called spawnBot() from which I call AIPlayer::spawnOnPath() with both parameters, a name and a path. The bot does spawn and from there I can tell it to followPath() and it does so.
function spawnBot()
{
$myNPC1 = AIPlayer::spawnOnPath("Shootme", "missiongroup/Paths/Path1");
}I call it from the console as spawnBot(), and then I tell it follow a path by doing this$myNPC1.followPath("MissionGroup/Paths/Path1", -1);Of course I think it would make much more sense to do something like this
function spawnBot()
{
%player = AIPlayer::spawnOnPath("Shootme", "missiongroup/Paths/Path1");
if (isObject(%player))
{
%player.followPath("MissionGroup/Paths/Path1", -1);
// slow this sucker down, I'm tired of chasing him!
%player.setMoveSpeed(0.5);
//%player.mountImage(xxxImage, 0);
//%player.setInventory(xxxAmmo, 1000);
}
}Which simply duplicates the AIManager::spawn() function. And after looking at it I would actually do something like this in order to extend it's functionalityfunction spawnBot(%botName, %pathToFollow)
{
%player = AIPlayer::spawnOnPath(%botName, %pathToFollow);
if (isObject(%player))
{
%player.followPath(%pathToFollow, -1);
// slow this sucker down, I'm tired of chasing him!
%player.setMoveSpeed(0.5);
//%player.mountImage(xxxImage, 0);
//%player.setInventory(xxxAmmo, 1000);
}
}That way if multiple paths are defined in a level then all you would have to is call spawnBot() with the appropriate parameters, like so:spawnBot("ShootMe", "missiongroup/Paths/Path1");
spawnBot("BulletSponge", "missiongroup/Paths/Path2");
spawnBot("TargetDummy", "missiongroup/Paths/Path3");voila: bots with different names and paths to follow.You could even go so far as to add another parameter in there that contains a datablock name for AIPlayer::spawn() to use, but that DBname would have to be passed from spawnBot() to AIPlayer::spawnOnPath() which in turn was modified to pass this extra parameter on to AIPlayer::spawn(). This would allow you to have different bot names, different paths, and different datablocks that bots would use, all called from the same reusable function but with different parameters.
#12
I finally got $mynpc1=AIPlayer::spawnOnPath("shootme",
"missiongroup/Paths/Path1"); to work!!!
My syntax was correct all along. Very simple function call, as it seemed it should be.
What was wrong then? Well, I did not realize that *which* file I called AIPlayer::spawnonpath from was important. Apparently, the file I called it from (a file I created to hold my own new assets and put in server/scripts) executes before the game loads up the object "missiongroup/paths/path1". Thus, of course, since it can't find that path, it fails.
....man, that took me a long time to realize.
Thanks so very much Michael for helping me till I figured it out.
07/31/2009 (6:15 am)
Great idea! I will certainly use this. It is the basis of just what I wanted...a way to spawn my own bots, on lots of different paths, the number of bots I want, and respawn according to my own algorithm. I finally got $mynpc1=AIPlayer::spawnOnPath("shootme",
"missiongroup/Paths/Path1"); to work!!!
My syntax was correct all along. Very simple function call, as it seemed it should be.
What was wrong then? Well, I did not realize that *which* file I called AIPlayer::spawnonpath from was important. Apparently, the file I called it from (a file I created to hold my own new assets and put in server/scripts) executes before the game loads up the object "missiongroup/paths/path1". Thus, of course, since it can't find that path, it fails.
....man, that took me a long time to realize.
Thanks so very much Michael for helping me till I figured it out.
#13
function GameCore::startGame(%game)
which resides in game/scripts/server/gamecore.cs. But what do I do/where do I place a call to execute a separate file in which I wish to place all my custom made AI stuff? The file I have it in now, actually executes after gamecore.cs, but I guess it does not stay running or something. I cannot get these functions to run from any script file other than gamecore.cs, and even then, I can only get them to run from
inside function GameCore::startGame(%game) .
07/31/2009 (9:06 am)
Well, I guess there is something I still don't understand. I can get some of these functions running from the console (I haven't tested all of them yet). I can also get them to run fine as long as I put them in the same function where AIManager starts, namely: function GameCore::startGame(%game)
which resides in game/scripts/server/gamecore.cs. But what do I do/where do I place a call to execute a separate file in which I wish to place all my custom made AI stuff? The file I have it in now, actually executes after gamecore.cs, but I guess it does not stay running or something. I cannot get these functions to run from any script file other than gamecore.cs, and even then, I can only get them to run from
inside function GameCore::startGame(%game) .
Torque Owner Javier Canon