Game Development Community

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.

#1
07/29/2009 (10:19 am)
you need to make paths in the terrain editors, then assign the path in script, search for the bot in the example mission.
#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
    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
    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
    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
    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
    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
    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
    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 functionality
    function 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
    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
    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) .