0
\$\begingroup\$

I'm working on coding enemy ai for a star fox-esqe shooter and I need the enemy to approach the player, stay a certain distance away and stay in front of them until destroyed. I can get the enemy to approach the player and I can get the enemy to stay a certain distance from the player but I'm not sure how to get the enemy to actually stay in front of the player. For a bit of extra information, the player makes a number of sharp turns and the like throughout the level. Also, as a stand in I tried simply causing the enemy to parent to the player within a certain radius but that causes clipping issues with buildings and the ground.

public class EnemyCar: MonoBehaviour
{
    public float safeDistance = 20f; // How close the enemy can get to the player


    // ...

    // Update is called once per frame
    void Update()
    {
        transform.LookAt(player.transform);

        Vector3 targertLocation = player.transform.position - transform.position;
        float distance = targertLocation.magnitude;

        // Decrease our speed as we get closer
        rb.AddRelativeForce(Vector3.forward * Mathf.Clamp((distance - 30) / 50, 0f, 1f) * thrust);
    }
}
\$\endgroup\$
0
\$\begingroup\$

You can do this by keeping track of a desired position relative to the player's view, or current frame of reference:

Vector3 desiredOffsetFromPlayer;

You can update this variable to make it approach the player or follow any arbitrary curve in its holding pattern in front of the player.

Then you can transform this into an actual world position like so:

Vector3 desiredPosition = player.transform.TransformPoint(desiredOffsetFromPlayer);

Now you can apply your navigation forces to seek toward that point (in FixedUpdate, for consistency regardless of framerate), or use physics queries to find the closest you can get to that point without clipping an obstacle.

Here's one potential way to do it:

void FixedUpdate() {
    // If you want to animate the holding position, update desired offset here.

    Vector3 desiredPosition = player.transform.TransformPoint(desiredOffsetFromPlayer);

    // How do we need to move to reach our target in this physics step?
    // You can also add the player velocity here to match course with them.
    Vector3 desiredVelocity = (desiredPosition - rb.position)/Time.deltaTime;

    // Clamp this within what our vessel is physically allowed to do.
    // (Here I assume we can thrust in any direction without turning around first)
    float maxDeltaV = maxThrust * Time.deltaTime;
    Vector3 deltaV = Vector3.ClampMagnitude(desiredVelocity - rb.velocity, maxDeltaV);

    // Accelerate to apply the needed correction.
    rb.AddForce(deltaV, ForceMode.VelocityChange);
}
\$\endgroup\$
7
  • \$\begingroup\$ What's desiredOffsetFromPlayer ? I don't understand, do I update it with desiredOffsetFromPlayer = player.transform.position - transform.position; ? \$\endgroup\$ – Johnny Bra Mar 21 '20 at 16:12
  • \$\begingroup\$ Desired Offset From Player is where you want to be in the player's frame of reference. So, if you want to be 10 meters ahead of the player, set it to (0, 0, 10). If you want to shift 3 units to their left and 2 units up, so you're diagonally a little out of the center of their screen, set it to (-3, 2, 10) \$\endgroup\$ – DMGregory Mar 21 '20 at 16:23
  • \$\begingroup\$ Can I set it to be in camera's view as well? Vector3 ScreenMidPoint = Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, DistanceFromCamera)); \$\endgroup\$ – Johnny Bra Mar 21 '20 at 16:39
  • \$\begingroup\$ You absolutely can. Try it! \$\endgroup\$ – DMGregory Mar 21 '20 at 16:43
  • \$\begingroup\$ Thank you for your help!! And one last question how can I add the player velocity here to match course with them? To this line of code Vector3 desiredVelocity = (desiredPosition - rb.position) / Time.deltaTime; \$\endgroup\$ – Johnny Bra Mar 21 '20 at 16:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.