Circling a target

This page describes how to make an agent move in a circle around a target.

Sometimes moving to a destination is not enough. You may need the agent to follow a target at an offset, circle a given target or anything else which is not just moving to a point. This can be acomplished by updating the movement script's destination field every frame (or as often as you need to).

For example, to make an agent move in a circle around a target, we will need to set the destination to some point slightly ahead of the agent, so that it moves along the border of the circle.

We can calculate this by taking the vector from the target to the agent and normalizing it, calling this the normal. Then we can take the normal and rotate it 90 degrees. Call this the tangent. Our agent's destination then becomesai.destination = target.position + normal * r + tangent * k
.

We want to place the destination a small distance away from the agent, as otherwise it may slow down because it thinks it is almost at the destination.

If we do this calculation every frame, and assign the destination to the agent, it will move in a circle around the target like in the video above.

In code, it would look something like this:

public class MoveInCircle : VersionedMonoBehaviour {
public Transform target;
public float radius = 5;
public float offset = 2;

IAstarAI ai;

void OnEnable () {
ai = GetComponent<IAstarAI>();
}

void Update () {
var normal = (ai.position - target.position).normalized;
var tangent = Vector3.Cross(normal, target.up);

ai.destination = target.position + normal * radius + tangent * offset;
}

public override void DrawGizmos () {
if (target) Draw.Circle(target.position, target.up, radius, Color.white);
}
}

See

This is implemented in the MoveInCircle component included in the package.

You can use the same kind of setup to make the agent follow a target at an offset: update the agent's destination every frame to the target's position plus an offset.

Note

This solution will be smoothest with the FollowerEntity movement script, as it repairs its path every time you set the destination, to make it always up to date. It will work for other movement scripts as well, but you may have to reduce the time between path recalculations to make it smoother.