I’m working on a basic 2D platformer where NPCs chase the player and I’ve been bashing my head against a problem for days.
I use A* pathfinding to chart a path from the Guard to the player. It’s supposed to stop a certain distance away from the player if they’re not moving (playerClosingDistance
). Currently what happens, however, is that in some cases the Guard will stop at the right distance, and sometimes it’ll overshoot, landing either right next to the player, on the player, or even passing through and turning around in rare cases.
Option 1
It could be as a result of the movement script on its own:
if (Mathf.Abs(distanceToPlayer) > playerClosingDistance)
{
// General Movement
body.velocity = new Vector2(direction.x * speed, body.velocity.y);
anim.SetBool("Running", true);
}
else
{
// Stop running
body.velocity = new Vector2(0, body.velocity.y);
anim.SetBool("Running", false);
}
Is that likely to be the problem? If so, what changes can I make?
Option 2
If it’s not the problem, my other areas of consideration are the use of the A* pathfinding itself.
A few salient parts of the script:
public void Start()
{
InvokeRepeating("UpdatePath", 0f, pathUpdateSeconds);
}
private void UpdatePath()
{
if (targetTransform == playerTransform) // for offsetting to player mid-body
{
targetTransformWithOffset = new Vector2(targetTransform.position.x, targetTransform.position.y + playerHeightOffset);
}
if (followEnabled && TargetInDistance() && seeker.IsDone())
{
seeker.StartPath(body.position, targetTransformWithOffset, OnPathComplete);
}
}
private void FixedUpdate()
{
// If there's no target, don't go anywhere
if (targetTransform == null)
{
followEnabled = false;
}
else
{
followEnabled = true;
}
// Target in Distance?
if (TargetInDistance() && followEnabled)
{
PathFollow();
}
}
private void PathFollow()
{
if (path == null)
{
// We have no path to follow yet, so don't do anything
return;
}
// reached end of path
if (currentWaypoint >= path.vectorPath.Count)
{
return;
}
Vector2 direction = ((Vector2)path.vectorPath[currentWaypoint] - body.position).normalized; // means that no matter the waypoint distance it only looks at the direction
// Movement Options
// Player is the target - only one for now
if (targetTransform == playerTransform)
{
float distanceToPlayer = Vector2.Distance(transform.position, playerTransform.position);
playerIsTarget(distanceToPlayer, direction);
}
}
I don’t know if any of these are non-standard; I followed a tutorial and made some basic edits for flexibility. I’m hoping it’s something easy to fix, but I’ve tried everything I can think of except workarounds instead of fixes (e.g. slowing the guard on approach to the player, repelling them a certain distance from player, etc.)