View Issue Details
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0002688||The Dark Mod||AI||public||11.03.2011 04:28||24.11.2017 16:33|
|Product Version||TDM 1.04|
|Summary||0002688: AI walk in a circle|
|Description||Not those very large circles defined by path_corners, but the tight circles when they get stuck trying to move past something. Circling more than one or two times should not be allowed.|
|Tags||No tags attached.|
After testing both distance-based and yaw-based solutions, I'm beginning to think that trying to solve the problem after the fact isn't going to be easy, and perhaps not possible. After recognizing a circling condition, each attempt to break the cycle by sending the AI elsewhere quickly fails as pathfinding undoes the request and puts the AI right back into the cycle.
Using debug drawing of obstacle recognition and pathfinding, I can see that even w/o corrective measures, pathfinding for a brief moment gives the AI a good path around an obstacle, but as the AI begins to walk toward the first goal point, subsequent pathfinding sends him back to where he was. This causes the AI to circle around to get back to that goal point. When he gets there, pathfinding finds the correct path again, then throws it away as soon as the AI begins to follow it.
Pathfinding's recalculation of a path each frame can discover a good path one frame, and a bad path the next.
So solving the circling problem will probably require some tweaking of pathfinding.
You could experiment with this section of code in idAI::AnimMove():
// greebo: This should take care of rats running around in circles around their goal
// due to not turning fast enough to their goalPos, sending them into a stable orbit.
float oldTurnRate = turnRate;
if (physicsObj.GetMass() <= SMALL_AI_MASS)
rad = 50;
rad = 100;
DM_LOG(LC_AAS, LT_DEBUG)LOGSTRING("idAI::AnimMove - %s - origin = [%s] oldTurnRate = %f dist to goal = %f\r", GetName(), physicsObj.GetOrigin().ToString(),oldTurnRate, (goalPos - physicsObj.GetOrigin()).LengthFast()); // grayman debug
DM_LOG(LC_AAS, LT_DEBUG)LOGSTRING("idAI::AnimMove - %s - bounds = [%s] rad = %f\r", GetName(), physicsObj.GetBounds().ToString(),rad); // grayman debug
gameRenderWorld->DebugArrow(colorRed, physicsObj.GetOrigin(), goalPos, 1, 60); // grayman debug
if ((goalPos - physicsObj.GetOrigin()).LengthSqr() < Square(rad))
//if ((goalPos - physicsObj.GetOrigin()).LengthSqr() < Square(50))
turnRate *= gameLocal.random.RandomFloat() + 1;
DM_LOG(LC_AAS, LT_DEBUG)LOGSTRING(" %s - temporary turnRate = %f\r", GetName(), turnRate); // grayman debug
// greebo: Now actually turn towards the "ideal" yaw.
A good test case is the bridge in searching.map (in Cleighmoor/maps). Get someone to chase you onto the main bridge, then run onto one of the side supports. When the test distance is 50 (set for rats), an AI can circle for a long time before coming onto the support. When the test distance is 100, they usually circle once and then come after you.
It's an improvement, but you need to test what this does to other turns, like when the AI is walking normally or navigating a door.
Something else to consider:
Turning is controlled by the turn rate, which is fixed. If, when starting a turn, instead of using a constant turn rate, try dividing the turn into smaller turns, each of which gets an increasingly larger turn rate. Work the math so that the last small turn and its rate put the AI on the path straight to the goal, ending the turn.
This seems like it might keep AI from getting stuck in these endless circles.
|11.03.2011 04:28||grayman||New Issue|
|11.03.2011 04:28||grayman||Status||new => assigned|
|11.03.2011 04:28||grayman||Assigned To||=> grayman|
|11.01.2012 05:31||grayman||Note Added: 0004233|
|30.12.2014 23:30||grayman||Note Added: 0007282|
|24.01.2015 19:00||grayman||Note Added: 0007388|
|24.11.2017 16:33||grayman||Assigned To||grayman =>|
|24.11.2017 16:33||grayman||Status||assigned => acknowledged|