how to make the npc follow a moving target(moved by physics) smoothly?
Hi, I have several NPC want to follow the player, if the player stand still, I can use liner interpolation to move the npc towards the player's position, and it works well, however, it's jiggle if the player is moving as well(player is moved by force with physics, but npc is just controlled by updating the position directly). Any ideas to make the npc to follow the player smoothly? Thanks
The simplest controller you could try would be a proportional one.
Call the player's position vector 'r.' Call the NPC's position vector 'x.' Suppose that the NPC has dynamics,
x[k+1] = x[k] + u[k] dt
where 'k' is the index of the current simulation step, u[k] is the velocity (you can choose it), and dt is the size of the timestep. Then a proportional controller would select u[k] at each time as,
u[k] = g(r[k] - x[k])
where 'g' is some constant. This will result in closed-loop dynamics (just plugging the second equation into the first),
x[k+1] = x[k] + k(r[k] - x[k]) dt
= (1 - g dt) x[k] + (g dt) r[k]
This will be stable so long as
-1 < 1 - g dt < 1
or equivalently,
0 < g < 2/dt ;
I would suggest a g in the range
0 < g < 1/dt
to avoid oscillation.
This is the simplest controller you can use. If it works, problem solved. If the performance isn't good enough (i.e., if you can't catch the target because it moves too much), you can add integral terms; if you find that's necessary, post back and I can explain that.
Call the player's position vector 'r.' Call the NPC's position vector 'x.' Suppose that the NPC has dynamics,
x[k+1] = x[k] + u[k] dt
where 'k' is the index of the current simulation step, u[k] is the velocity (you can choose it), and dt is the size of the timestep. Then a proportional controller would select u[k] at each time as,
u[k] = g(r[k] - x[k])
where 'g' is some constant. This will result in closed-loop dynamics (just plugging the second equation into the first),
x[k+1] = x[k] + k(r[k] - x[k]) dt
= (1 - g dt) x[k] + (g dt) r[k]
This will be stable so long as
-1 < 1 - g dt < 1
or equivalently,
0 < g < 2/dt ;
I would suggest a g in the range
0 < g < 1/dt
to avoid oscillation.
This is the simplest controller you can use. If it works, problem solved. If the performance isn't good enough (i.e., if you can't catch the target because it moves too much), you can add integral terms; if you find that's necessary, post back and I can explain that.
Quote:
Original post by Emergent
The simplest controller you could try would be a proportional one.
Call the player's position vector 'r.' Call the NPC's position vector 'x.' Suppose that the NPC has dynamics,
x[k+1] = x[k] + u[k] dt
where 'k' is the index of the current simulation step, u[k] is the velocity (you can choose it), and dt is the size of the timestep. Then a proportional controller would select u[k] at each time as,
u[k] = g(r[k] - x[k])
where 'g' is some constant. This will result in closed-loop dynamics (just plugging the second equation into the first),
x[k+1] = x[k] + k(r[k] - x[k]) dt
= (1 - g dt) x[k] + (g dt) r[k]
This will be stable so long as
-1 < 1 - g dt < 1
or equivalently,
0 < g < 2/dt ;
I would suggest a g in the range
0 < g < 1/dt
to avoid oscillation.
This is the simplest controller you can use. If it works, problem solved. If the performance isn't good enough (i.e., if you can't catch the target because it moves too much), you can add integral terms; if you find that's necessary, post back and I can explain that.
Thanks, my way is similar to yours:
Vector3 dir = player.position - npc.position;
dir.Normalize();
Vector3 targetpos = player.position - dir * mDistance; //mDistance is to avoid the npc getting too close to the player
float factor = Mathf.Min(1.0f, Updater.deltaTime*5.0f);
npc.position = Interpolation.Linear(npc.position, targetpos, factor);
dir = player.position - npc.position;
npc.rotation = Interpolation.Linear(npc.rotation, Quaternion.LookRotation(dir), factor);
Vector3 Linear(Vector3 v0, Vector3 v1, float factor)
{
return v0 * (1.0f - factor) + v1 * factor;
}
However, it's not smooth enough. If the player stands still, it works well, but if the player is moving with a changing velocity calculated from the forces applied by physics engine, the movement of the npc is jiggle. So I suspect the reason is the target is moving with a changing velocity. I tried to use the average position of the player from the last 30 frames as the target position, it seems not working either.
Quote:
Original post by jyou23
my way is similar to yours:
Ok, I see; rather than using a proportional ("P") controller to get the NPC to the player's position, you use one to get the NPC to the closest point on a sphere of radius mDistance surrounding the player. And, translating to my notation, your control gain is chosen to be
g = min{5, 1/dt}
which is indeed stable.
Quote:
However, it's not smooth enough. If the player stands still, it works well, but if the player is moving with a changing velocity calculated from the forces applied by physics engine, the movement of the npc is jiggle. So I suspect the reason is the target is moving with a changing velocity. I tried to use the average position of the player from the last 30 frames as the target position, it seems not working either.
I'm surprised that you get unacceptable "jiggle" with a P controller. Is your control gain (factor) just too high?
If not, then the first thing I'd try is what you did, which is to filter the reference. What didn't work about your average-position-over-last-30-frames method?
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement