Game Development Community

dev|Pro Game Development Curriculum

Path Following AI Vehicles Through TorqueScript

by Quentin Headen · 06/03/2010 (11:02 pm) · 8 comments

NOTE: If you are using Torque 3D Pro or TGEA, please go to my other resource here in order to get the AIWheeledVehicle class into the engine! Without it, this resource won't work. Once that is done, you can implement this resource.

In Torque, the AIWheeledVehicle class is a very useful class to get you started with AI vehicles driving around. The only problem is that they can't follow paths like AI players can out of the box. There is an excellent resource by Mr. Brian McGavin (www.torquepowered.com/community/resources/view/8836) that adds this path-following functionality by modifying the Torque source code.

In this resource though, we are going to implement the same kind of functionality to allow stock AIWheeledVehicles to follow a path without any engine modification at all; just utilizing the object functions exposed to TorqueScript out of the box.

Here is the TorqueScript script file you need to use:

//The AICarManager object is a script object used
//for updating AIWheeledVehicles. It allows them to
//follow in game paths without modification to the
//source code of the engine.

//By Quentin Headen

new ScriptObject(AICarManager)
{
   botGroup = 0; //A SimGroup object containing all of the ai cars (bots)
   arrivedDistance = 8; //The distance from the destination that the bot can say it arrived
   updateSpeed = 100; //The speed at which the manager rechecks the bots
   botMoveSpeed = 0.5; //The movement speed of the bots. Start at half.
   thinkSchedule = 0; //The schedule to update the thinking
};

function AICarManager::think(%this)
{   
   //If the bot group isn't set
   if(!isObject(%this.botGroup))
   {
      //Show an error and return
      error("You must set the botGroup SimGroup using setBotGroup before thinking can occur!");
      return;
   }
   
   //For each vehicle bot in the bot group
   for(%i = 0; %i < %this.botGroup.getCount(); %i++)
   {
      //Get the bot object
      %bot = %this.botGroup.getObject(%i);
      
      //If the path for this vehicle bot
      //is set
      if(isObject(%bot.path))
      {
         //Check the distance from the bot to its current path node
         %distance = VectorDist(%bot.getPosition(), %bot.path.getObject(%bot.pathNode).getPosition());
         
         //If the distance is less than the arrived distance
         if(%distance < %this.arrivedDistance)
         {
            //Move to the next node
            %bot.pathNode++;
            
            //If that node dosen't exist
            if(%bot.pathNode > %bot.path.getCount() - 1)
            {
               //Move back to the beginning node
               %bot.pathNode = 0;
            }
            
            //Set the updated move destination
            %bot.setMoveDestination(%bot.path.getObject(%bot.pathNode).getPosition());
         }
      }
   }
   
   //Continue to think
   %this.thinkSchedule = %this.schedule(%this.updateSpeed, think);
}

function AICarManager::startBot(%this, %bot, %path)
{
   //If the bot group doesn't exist
   if(!isObject(%this.botGroup))
   {
      //Create it
      %this.botGroup = new SimGroup();
   }
   
   //If this bot isn't a member of the bot group
   if(!%this.botGroup.isMember(%bot))
   {
      //Add it
      %this.botGroup.add(%bot);
   }
   
   //Set the starting path and path node for the bot
   %bot.path = %path;
   %bot.pathNode = 0;
   
   //Start the car to moving
   %bot.setMoveSpeed(%this.botMoveSpeed);
   %bot.setMoveDestination(%path.getObject(0).getPosition());
}

function AICarManager::stopBot(%this, %bot)
{
   //If the bot is in the bot group
   if(%this.botGroup.isMember(%bot))
   {
      //Stop it
      %bot.stop();
      
      //Remove it from the manager
      %this.botGroup.remove(%bot);
   }
}

function AiCarManager::stopThinking(%this)
{
   //Cancel the updating of the think() function
   cancel(%this.thinkSchedule);
   
   //For each car in the bot group
   for(%i = 0; %i < %this.botGroup.getCount(); %i++)
   {
      //Stop it
      %this.botGroup.getObject(%i).stop();
   }
}

I know you probably don't believe that this is the only script you have to add. Don't feel bad, I almost didn't believe it myself. :P

To see this script in action, open up a mission, create a path, create an AIWheeledVehicle and then call AICarManager.startBot(BotNameOrID, PathNameOrID); Remember that "BotNameOrID" is equal to the name or ID of the AIWheeledVehicle you want to follow a path and "PathNameOrID" is equal to the name or ID of the path your desired bot should follow. After that, the car will begin to move. MAKE SURE that you call AICarManager.think() right after this or the car won't follow the path, but will be stuck at the first node of the path. If you ever need to stop all of your bots from following the path, just call AICarManager.stopThinking(). This will kill the think loop and stop all of the bots added to this manager. To stop a single bot, just call AICarManager.stopBot(BotNameOrID), with once again BotNameOrID meaning the name or ID of the bot you want to stop.

Please note that this script isn't completely done. I have some extra things I want to add such as slowing down the car when it approches a node.

Hmm... What else is there to tell you? I know it was something extra I had to tell you about this script... Oh yeah, I remember! I wanted to tell you to HAVE FUN! :)

Please make comments on the script to let me know how you like it and what improvements can be made.


Edit: Changed the way the script determines if there is a next node. The old method littered the console with getObject() out of range errors.

About the author

Just your average programmer who tries to finish the projects he starts. :) I am currently focused on creating games with Torque engines. My website is http://phaseshiftsoftware.com


#1
06/04/2010 (2:50 am)
nice work Quentin. T3D port of this would be awesome.. from the look of it, not much would need to be changed.
#2
06/04/2010 (2:53 am)
I coult not find any "AIWheeledVehicle" in the source code of T3D. I think you'r right.
#3
06/04/2010 (6:26 am)
One source for AiWheeledVehicle www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=8836 I have a version running in T3D already so it does compile.

Nice resource, thank you.
#4
06/04/2010 (9:19 am)
Thanks for the comments everyone! I really hope that GarageGames brings back the AIWheeledVehicle class. For those who want to make racing games, they shouldn't have to pay the full $1,000 just to add this class.

I would love to just get the $100 version of T3D, but since I'm into racing games and need AI cars, I would have to spend a whole $900 more just to add the AIWheeledVehicle class.

So if you are looking at this GarageGames, please take this thought into mind. T3D isn't just for walking characters and weapons ya know. ;)
#5
09/16/2010 (2:42 am)
if there are two bots in the botgroup and two different pathes.
how can i ask each bots follow each path.
Thank You!
#6
09/17/2010 (4:40 pm)
@zhengcarpenter

When you call the AICarManager::startBot method to make a bot start following a path, you pass the name or ID of the path in the last argument of the function. The whole function is like this AICarManager::startBot(%this, %bot, %path).

So for example, if you have a bot named CoolBot and you have a path named CurvyPath you would call the function like this %managerName.startBot(CoolBot, CurvyPath). Remember to replace %managerName with the name of the AI Manager you created.

As you can see, the first argument is the bot itself. The second argument is the path. So just make sure you set the second argument to the path you want.
#7
03/23/2011 (7:38 am)
hi Quentin,
any updates to this yet?
#8
03/23/2011 (11:24 am)
@deepscratch

No, no updates. I haven't been able to add the changes I wanted because I've been busy on other stuff. Between school, and me working on my 2D game in TGB, I haven't been able to really work with Torque 3D yet.

I purchased T3D because of the insanely low price, and I want to make my next game in 3D. So after I finish my current game, which shouldn't be too long from now, I'll get back to Torque 3D, and start making improvements on this resource.

I plan on making a racing game with Torque 3D, so I'm sure I'll end up releasing more resources, as T3D isn't that jaw-dropping when it comes to vehicular stuff.