Jump to content

NPC Control


Clackdor
 Share

Recommended Posts

This is a more high level question based around programming technique.

 

I have programed my NPC skeleton class in "Swords and Skellies" to take commands, but not to determine its own behavior.

 

The behavior is based on the player position and whether she is armed or not. I have a procedural program that calls one of 7 class functions to tell the skeleton what to do: Idle, Pursue, Flee, Attack, Die, Revive, Return (to start position). I could make all the behavior governed inside the object.

 

How do others do this? Do you think it would be wise to have all of the behavior defined in the object instead of having the procedural program make the call? Is this a pure style question? Other opinions?

Link to comment
Share on other sites

I recommend the book Programming Game AI by Example. http://www.amazon.com/Programming-Game-Example-Mat-Buckland/dp/1556220782

 

It goes beyond just presenting theory and gives you actual C++ code you can use in your own projects. If you're new to programming AI (like myself), it may take a while to wrap your head around it and adapt the example code to your own purpose, but the effort is well worth it.

 

A Finite State Machine is a good solution to the problem you described. The book gives you all the information and examples needed to implement your own FSM. It's much easier to understand if you're already familiar with virtual functions and interface classes. The examples also makes use of the Standard Template Library, so you'll want to be familiar with that as well.

Link to comment
Share on other sites

I too use Finite State Machines for my NPC behaviour.

 

I have a FSM defined for each NPC type and my NPC update routine simply calls the FSM update routine from its own update routine which is in turn called from an update event triggered from the game loop.

 

The FSM contains all the behavior logic and responds to various input stimuli such as line of sight input, sound input, NPC state input etc and interfaces with my path finding functionality to determine NPC movement and switching between different NPC states which control the aspects of the behaviour etc.

 

So the top of my NPC class update routine simply looks like this:

 

void npc::update(float gameLoopTime)
{
// Update the controller position
m_vecControllerPos = EntityPosition(this->m_NPCController,1);

// Update the wait timer if activated
if(m_bTimerActive)
{
	updateTimer();
}

// Update the State Machine
if(bNavDataLoaded && !m_bDisableFSM)
{
	m_pStateMachine->Update();
}

// Handle weapon fire
if(m_bFireWeapon || m_bWeaponIsFiring)
{
	updateWeaponFire(gameLoopTime);
}

// If nothing to do then simple return
if(!m_bHasUpdateWork) return;

// If currently moving then update movement
if(m_bIsMoving)
{
	....

 

Some examples of the many states I use are:

 

idle

patrol

moveToPosition

moveToCover

moveToCoverFirePointPos

closeOnEnemy

attackEnemy

defendPosition

hit

waitThenTriggerState

 

 

Behavior trees can also be used and offer certain advantages over FSMs but then have some disadvantages too.

Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++

Link to comment
Share on other sites

..i do it in such way that, I have one 'central' class called TBrain..this class knows everything about every NPC out there..one of known features is also 'idle state' of each NPC, therefore, TBrain will approach ONLY NPC outside of its own 'idle state'. For NPC what are considered in 'idle state' , they will be left to update itself so AI doesnt spending any time on them. Soon as NPC goes outside of 'idle state' (reporting to TBrain), TBrain will check TBehaviour member of NPC class and based on that, determine what to do with given NPC. On that way, system is rather fast, and whole structure update itself only when it have to. It works on massive number of NPC's (crowd simulation) very very well..recently i read, similar approach is used over Left4dead actually..

 

Link to comment
Share on other sites

I don't believe operationally there is any advantage in what your describing NA. Whatever checks are required to determine what triggers an NPC to come out of Idle state have to be done regardless of what system you are using, in mine it's in the FSM but there is little overhead associated with this, if no other state is triggered it simply returns.

Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++

Link to comment
Share on other sites

..well..i believe there is..instead of checking whole structure, each NPC has its own cycle where is performed basic check over 'idle state'. If NPC 'idle state' is intruded by other NPC at that time driven by TBrain, whole lookup cycle is skipped on side of intruded NPC, because TBrain know its already intruded and performing all operations over intruded NPC. While it doesnt look much, in actual crowd simulation it shows massive speed gain simply because less individual lookups are performed, more AI is involved. There are several advantages over various NPC types behaviour with such system as it is independent from NPC structure itself. Also, some NPC's can be determined as a 'STATIC' in terms of AI, and they will not update even itself, until TBrain set them to do so (example is guards standing at entrance, reacting only if certain characters approach them, controlled by TBrain).

 

Link to comment
Share on other sites

..well..i believe there is..instead of checking whole structure, each NPC has its own cycle where is performed basic check over 'idle state'.

Well in my FSM any NPC in the idle state will automatically drop into the idle state processing code and perform the exact same checks that presumably your NPC idle state cycle checks, that is anything that might cause the NPC to come out of the Idle state. If non of these trigger a state change no further processing is done, where is the difference.

 

If NPC 'idle state' is intruded by other NPC at that time driven by TBrain, whole lookup cycle is skipped on side of intruded NPC, because TBrain know its already intruded and performing all operations over intruded NPC.

Same with the FSM, once the idle state has been triggered to something else the FSM will process the new state and no further processing of the idle state will take place. There is no way of avoiding the state control for what ever state an NPC is in at any given point in time, all you can do is avoid calling additional code which is of no benefit at the time. FSMs do this quite elegantly if designed well.

 

Maybe I am not understanding your explanation well enough to see what you are really citing as an advantage.

 

Either way, debating aside, I hope Clackdor has enough food for thought to do some investigation into these areas of AI control.

Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...