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);
}
}
}