Source file unity-csharp/nature-of-code/seek-and-arrive-2d/Vehicle2D.cs from the GDnD code examples. Download raw file

// GDnD wiki example
// Demonstrates: seek and arrive steering in Unity 2D
// Related pages: [[steering-behaviours]], [[overview-unity-nature-of-code-examples]]
 
using UnityEngine;
 
public class Vehicle2D : MonoBehaviour
{
    [SerializeField] private float maxSpeed = 6f;
    [SerializeField] private float maxForce = 12f;
    [SerializeField] private float slowRadius = 2f;
    [SerializeField] private bool orientToVelocity = true;
 
    private Vector2 velocity;
    private Vector2 acceleration;
 
    public Vector2 Position => transform.position;
    public Vector2 Velocity => velocity;
    public float MaxSpeed => maxSpeed;
    public float MaxForce => maxForce;
    public float SlowRadius => slowRadius;
 
    public void ApplyForce(Vector2 force)
    {
        acceleration += Vector2.ClampMagnitude(force, maxForce);
    }
 
    public Vector2 Seek(Vector2 target)
    {
        Vector2 desired = (target - Position).normalized * maxSpeed;
        return Vector2.ClampMagnitude(desired - velocity, maxForce);
    }
 
    public Vector2 Arrive(Vector2 target)
    {
        Vector2 toTarget = target - Position;
        float distance = toTarget.magnitude;
 
        if (distance <= Mathf.Epsilon)
        {
            return -velocity;
        }
 
        float targetSpeed = distance < slowRadius
            ? Mathf.Lerp(0f, maxSpeed, distance / slowRadius)
            : maxSpeed;
 
        Vector2 desired = toTarget.normalized * targetSpeed;
        return Vector2.ClampMagnitude(desired - velocity, maxForce);
    }
 
    private void Update()
    {
        float dt = Time.deltaTime;
 
        velocity += acceleration * dt;
        velocity = Vector2.ClampMagnitude(velocity, maxSpeed);
        transform.position += (Vector3)(velocity * dt);
        acceleration = Vector2.zero;
 
        if (orientToVelocity && velocity.sqrMagnitude > 0.0001f)
        {
            float angle = Mathf.Atan2(velocity.y, velocity.x) * Mathf.Rad2Deg;
            transform.rotation = Quaternion.Euler(0f, 0f, angle);
        }
    }
}