Advertisement

NPC wobbles after reaching destination

Started by July 01, 2024 08:12 PM
3 comments, last by nortski 4 months, 3 weeks ago

I have some simple chase behaviour setup on my npcs that have a “follow” component.
If the npc can see the player and is within attack distance it will then move towards the player. The npc will return to it's original position if the player goes out of sight or our of range of the npc.

My problem is the npc will wobble at it's destination, either after reaching the player's position or returning back to it's home position.

I am a beginner and I feel I'm just missing out a simple step. Can you guys please take a look at my code and advise me:

if(!visionBlocked && (playerPos.dist(npcPosition) < 300))
{
	direction = playerPos - npcPosition;
}
else
{
	direction = homePos - npcPosition;
}

direction.normalize();
direction *= npc->getComponent<CFollow>().speed;
npcPosition += direction;

This is caused by the phenomenon of “overshoot”, a common issue in many disciplines when trying to iteratively reach a target value. This happens in spring simulations, PID controllers, etc. It can happen anywhere you iteratively use a formula like: velocity = (target - current)*speed.

You are trying to go exactly to the target position at full speed, but due to inaccurate numerical integration of the time step, will go past the target position. The solution is to add damping, so that overshoot is avoided. This could involve slowing down when in the vicinity of the target.

You might want to set speed like this:

// speedFactor controls how much to slow down.
speed = min( speedFactor*length(playerPos - npcPosition), maxSpeed );

This will cause the NPC to slow down when it is near the player, since the speed is proportional to the distance. Since speed will be slower, overshoot is mostly avoided since you travel less distance in each time step. The speed is limited to a maximum value, to avoid moving too fast when far away.

Advertisement

In addition to the overshoot issue, be generous about the destination. Accept “close enough” if you are using steering and velocity to get to the target, and once it is within a broad tolerance, put on the brakes.

Then regardless of the reason for not being perfect, from rounding errors to overshot to Zeno's Paradox, it often feels more realistic to have a little imperfection. It also helps against minor collision issues, rather than fighting to reach a specific pixel and laser-focused to stop exactly on the spot, objects are more relaxed.

Thank you guys. So this is “arrival behaviour” right? I've got it working now by setting the direction velocity to 0 if the npc is within 5px of it's target.

This topic is closed to new replies.

Advertisement