Game Development Community

T3D 1.1 Final - Slowing Ai Think They're Stuck - w/Fix - RESOLVED (THREED-1977)

by Steve Acaster · in Torque 3D Professional · 06/06/2011 (12:20 pm) · 9 replies

T3D 1.1 Final

win7 32bit

Target:
Ai scripts/code, movement, onMoveStuck

Issue:
As an Ai approaches it's destination, it calls onMoveStuck and starts "freaking out" a bit until it finally inches to it's goal and halts. This is because of it's "mMoveSlowdown" variable so that it reduces speed to move smoothly to a stop rather than a sudden halt.

There is a failsafe to prevent onMoveStuck from happening when an Ai starts moving, but not when it starts to stop moving.

from aiplayer.cpp
Quote:
addField( "moveStuckTestDelay", TypeS32, Offset( mMoveStuckTestDelay, AIPlayer ),
"@brief The number of ticks to wait before testing if the AIPlayer is stuck.nn"
"When the AIPlayer is asked to move, this property is the number of ticks to wait "
"before the AIPlayer starts to check if it is stuck. This delay allows the AIPlayer "
"to accelerate to full speed without its initial slow start being considered as stuck.n"
"@note Set to zero to have the stuck test start immediately.n");

Repeat:
Make sure you have an echo in scripts/server/aiplayer.cs "funtion DemoPlayer::onMoveStuck" and "function DemoPlayer::onReachDestination". Spawn an Ai, have them run to a final destination (not a looping path or they'll never stop) and watch them struggle with the final steps and "freak out" whilst they do it. Check the console for onMoveStuck callback spam.

Having slower moving Ai (stock AiManager has the Ai slowed down by 50% - %player.setMoveSpeed(0.5)) makes this worse.


Suggest:
There are a few options available.
Lowering the maxDistance for starting slowdown - 5 units/m is kinda big and slowdown still looks fine when called at just 1 or 2 unit/m.
bool AIPlayer::getAIMove(Move *movePtr)
{
//...
         // Set movement speed.  We'll slow down once we get close
         // to try and stop on the spot...
         if (mMoveSlowdown) {
            F32 speed = mMoveSpeed;
            F32 dist = mSqrt(xDiff*xDiff + yDiff*yDiff);
            F32 maxDist = 2.0f;//5.0f;//yorks
            if (dist < maxDist)
               speed *= dist / maxDist;
            movePtr->x *= speed;
            movePtr->y *= speed;
         }
         else {
            movePtr->x *= mMoveSpeed;
            movePtr->y *= mMoveSpeed;
         }
//...
}

Whilst that is really a workaround, it might be best to actually prevent the onStuckMove callback being when the Ai is in "mMoveSlowDown".

//...
         // We should check to see if we are stuck...
            F32 locationDelta = (location - mLastLocation).len();
            if (locationDelta < mMoveStuckTolerance && mDamageState == Enabled) {//yorks added damageState check
				if (!mMoveSlowdown){//yorks added ignore if we are slowing down
				mMoveState = ModeStuck;
               throwCallback("onMoveStuck");
				}//yorks added this here
//...
Note: that includes my "not onMoveStuck when dead fix here

Whilst this stops the onMoveStuck callbacks, the Aiplayer does still "flip out" a bit (especially when moving slow - %player.setMoveSpeed(0.5) - and up an incline), which I suspect has more to do finalizing their mMoveTolerance distance from the destination than anything else - hence my first code change in mMoveSlowDown.

As ever, remember I'm not a programmer and just make this schtick up as I go (though I do test the hell out of it). :P

#1
06/06/2011 (12:25 pm)
Logged as THREED-1977.
#2
06/15/2011 (3:18 pm)
Bug confirmed.
#3
06/23/2011 (10:42 am)
Thanks Steve, didn't had the time myself to dig into it.
#4
08/08/2011 (1:46 pm)
Good catch Steve. Just one nitpick. I don't think this is doing exactly what you want it to do.

In the header of aiPlayer, you'll see that mMoveSlowdown is a bool that we use to determine if we should slow down as we reach our destination or not. Not a bool that is flipped on as we slow down. The fix you have above will prevent any AI that slows down from ever becoming "stuck", when really we just don't want to consider it stuck while it's slowing down.

This fix is similar, but not pretty.

In Engine/source/T3D/aiPlayer.h...
public:
	enum MoveState {
		ModeStop,                       // AI has stopped moving.
		ModeMove,                       // AI is currently moving.
		ModeStuck,                      // AI is stuck, but wants to move.
      ModeSlowing,                    // AI is slowing down as it reaches it's destination. <--ENUM ADDED
	};

And in aiPlayer.cpp make the following changes...

if (mMoveSlowdown) {
            F32 speed = mMoveSpeed;
            F32 dist = mSqrt(xDiff*xDiff + yDiff*yDiff);
            F32 maxDist = 5.0f;
            if (dist < maxDist)
               speed *= dist / maxDist;
            movePtr->x *= speed;
            movePtr->y *= speed;

            mMoveState = ModeSlowing; //<-- LINE ADDED

         }
         else {
            movePtr->x *= mMoveSpeed;
            movePtr->y *= mMoveSpeed;

            mMoveState = ModeMove; //<-- LINE ADDED
         }

         // Reset a previous stuck mode <-- DELETE THIS LINE
         //mMoveState = ModeMove; <-- DELETE THIS LINE TOO

Also:

if (locationDelta < mMoveStuckTolerance && mDamageState == Enabled) //<-- York's fix added
            { //BEGINCHANGES
               // If we are slowing down, then it's likely that our location delta will be less than
               // Our move stuck tolerance. Because we can be both slowing and stuck
               // we should TRY to check if we've moved. This could use better detection.
               if ( mMoveState != ModeSlowing || locationDelta == 0 )
               {
                  mMoveState = ModeStuck;
                  throwCallback("onMoveStuck");
               }//ENDCHANGES

Give that a try for me and let me know how it works for you.
#5
08/08/2011 (3:56 pm)
Seems to work, no stuck callbacks, though the Ai still does "freak out" a little as it gets to the end of it's destination.
#6
08/09/2011 (3:21 am)
Does the figure/sequence have proper Ground Transforms in the animation? ...just curious. IE< is it 'Gideon' or 'Soldier' you're looking at or a custom figure with custom animations?
#7
08/09/2011 (6:56 am)
Soldier, the "freak out" occurs when it's basicallt on top of the destination node but hasn't yet trigger the "arrived" callback. It seems to lose which direction the node is and thus wobble/spin like a cokehead.
#8
08/17/2011 (7:41 am)
Okay, the "freak out" occurs in stock because of very tiny rotations. Here's the fix for that linky, whilst the thread is marked as resolved but the code isn't in stock.
#9
10/08/2011 (11:38 am)
Fixed in 1.2.