简单介绍Steering Behavior,了解它的核心内容是什么

Steering Behavior

中文标准译法:转向行为 / 制导行为
多用于游戏AI、群体仿真、自动驾驶、机器人路径规划领域。

1. 核心定义

Steering Behavior 是一类局部运动智能算法,让虚拟角色/Agent 根据周围环境实时计算转向力,实现自然、平滑的移动,不需要预先规划完整路径。
由 Craig Reynolds 在1999年提出,是群体AI(Boids)的基础。

本质:输出一个转向矢量(steering force),用来修正当前速度,引导物体朝目标运动。

2. 常见基础 Steering Behavior(经典类型)

  1. Seek(追逐)
    朝着目标位置移动,持续逼近目标。
  2. Flee(逃离)
    远离威胁目标。
  3. Arrive(抵达)
    靠近目标时自动减速,平稳停下(Seek不会减速,会冲过目标)。
  4. Pursuit(追击)
    预判目标未来位置,追踪移动目标(比Seek更智能)。
  5. Evade(规避)
    预判移动物体轨迹,提前躲开。
  6. Wander(漫游/游荡)
    随机平滑转向,模拟漫无目的闲逛。
  7. Avoid Obstacle(障碍物规避)
    检测前方障碍,侧向绕行。
  8. Separation(分离)
    群体内个体互相推开,防止挤在一起(鸟群、人群必备)。
  9. Alignment(对齐)
    群体个体朝向与周围同伴运动方向保持一致。
  10. Cohesion(凝聚)
    向群体中心靠拢,维持集群。

Separation + Alignment + Cohesion = 经典 Boids 鸟群算法

3. 工作简易流程

  1. Agent 当前有速度向量 velocity
  2. 行为计算出期望速度 desired velocity
  3. Steering Force = desired velocity − current velocity
  4. 将转向力施加到物体,限制最大加速度、最大速度,更新位置

4. 使用场景

  • Unity / Unreal 游戏NPC、怪物、载具AI
  • 人群仿真、车流模拟
  • 无人机、机器人局部避障运动控制
  • 自动驾驶局部路径跟随

区分两个易混概念

  • Pathfinding(寻路):A*、NavMesh → 找整条静态路线(宏观)
  • Steering Behavior(转向行为):沿着路线平滑移动、避障、群体互动(微观运动控制)

如何实现 Steering Behavior 算法?

核心公式(重中之重)

SteeringForce(转向力)= DesiredVelocity(期望速度)− CurrentVelocity(当前速度)

约束:

  1. 转向力有最大上限 maxForce(避免瞬间急转)
  2. 物体有最大速度 maxSpeed
  3. 使用加速度更新速度,速度更新位置

运动更新统一框架(所有行为共用)

// 每一帧执行
steeringForce = 各个行为算出的转向力加权叠加
steeringForce = ClampMagnitude(steeringForce, maxForce);

velocity += steeringForce * deltaTime;
velocity = ClampMagnitude(velocity, maxSpeed);

position += velocity * deltaTime;

所有 Steering 行为,只是计算不同的 DesiredVelocity


一、逐个实现经典行为(向量伪代码)

假设向量库提供:Normalize()Magnitude()ClampMagnitude()

1. Seek 追逐(奔向目标点)

Vector3 Seek(Vector3 targetPos)
{
    Vector3 desiredVelocity = (targetPos - position).normalized * maxSpeed;
    Vector3 steering = desiredVelocity - velocity;
    return steering;
}

2. Arrive 抵达(靠近目标自动减速,不会冲过去)

Vector3 Arrive(Vector3 targetPos, float slowRadius)
{
    Vector3 toTarget = targetPos - position;
    float distance = toTarget.magnitude;

    Vector3 desiredVelocity;
    if (distance < 0.001f)
        desiredVelocity = Vector3.zero;
    else if (distance < slowRadius)
    {
        // 距离越近,速度越低
        float speed = maxSpeed * (distance / slowRadius);
        desiredVelocity = toTarget.normalized * speed;
    }
    else
    {
        desiredVelocity = toTarget.normalized * maxSpeed;
    }

    Vector3 steering = desiredVelocity - velocity;
    return steering;
}

3. Flee 逃离

Vector3 Flee(Vector3 threatPos)
{
    Vector3 desiredVelocity = (position - threatPos).normalized * maxSpeed;
    Vector3 steering = desiredVelocity - velocity;
    return steering;
}

4. Pursuit 预判追击(追踪移动目标)

思路:预测目标未来位置,再对预测点执行Seek

Vector3 Pursuit(Agent targetAgent)
{
    // 预估追击时间:距离/自身最大速度
    float dist = Vector3.Distance(position, targetAgent.position);
    float predictTime = dist / maxSpeed;

    // 预测目标未来位置
    Vector3 futureTargetPos = targetAgent.position + targetAgent.velocity * predictTime;
    
    return Seek(futureTargetPos);
}

5. Evade 预判躲避

和Pursuit相反,预测威胁位置然后Flee

Vector3 Evade(Agent threatAgent)
{
    float dist = Vector3.Distance(position, threatAgent.position);
    float predictTime = dist / maxSpeed;
    Vector3 futureThreatPos = threatAgent.position + threatAgent.velocity * predictTime;
    return Flee(futureThreatPos);
}

6. Wander 随机漫游(平滑闲逛,NPC常用)

原理:前进方向前方虚拟圆圈,随机取点作为临时目标

Vector3 Wander()
{
    // 1. 前进方向前方生成一个圆心
    Vector3 circleCenter = position + velocity.normalized * wanderDistance;
    // 2. 在圆上随机一点
    wanderAngle += Random.Range(-wanderAngleChange, wanderAngleChange);
    Vector3 offset = new Vector3(Mathf.Cos(wanderAngle), 0, Mathf.Sin(wanderAngle)) * wanderRadius;
    Vector3 target = circleCenter + offset;

    return Seek(target);
}

7. Boids三规则(群体行为,鸟群/人群)

Separation 分离(避免互相挤压)

Vector3 Separation(List<Agent> neighbors, float separationRange)
{
    Vector3 steer = Vector3.zero;
    int count = 0;
    foreach(var neighbor in neighbors)
    {
        float dist = Vector3.Distance(position, neighbor.position);
        if(dist > 0 && dist < separationRange)
        {
            // 距离越近排斥力越大
            Vector3 away = position - neighbor.position;
            away /= dist;
            steer += away;
            count++;
        }
    }
    if(count > 0)
    {
        steer /= count;
        steer.Normalize();
        steer *= maxSpeed;
        steer -= velocity;
    }
    return steer;
}

Cohesion 凝聚(向群体中心靠拢)

Vector3 Cohesion(List<Agent> neighbors, float cohesionRange)
{
    Vector3 center = Vector3.zero;
    int count = 0;
    foreach(var neighbor in neighbors)
    {
        float dist = Vector3.Distance(position, neighbor.position);
        if(dist < cohesionRange)
        {
            center += neighbor.position;
            count++;
        }
    }
    if(count == 0) return Vector3.zero;
    center /= count;
    return Seek(center);
}

Alignment 对齐(和同伴运动方向保持一致)

Vector3 Alignment(List<Agent> neighbors, float alignRange)
{
    Vector3 avgVel = Vector3.zero;
    int count = 0;
    foreach(var neighbor in neighbors)
    {
        float dist = Vector3.Distance(position, neighbor.position);
        if(dist < alignRange)
        {
            avgVel += neighbor.velocity;
            count++;
        }
    }
    if(count == 0) return Vector3.zero;
    avgVel /= count;
    avgVel.Normalize();
    avgVel *= maxSpeed;
    return avgVel - velocity;
}

鸟群最终转向力 = Separationw1 + Cohesionw2 + Alignment*w3

8. Obstacle Avoidance 障碍物规避

简化思路:

  1. 沿自身前进方向发射探测射线
  2. 如果前方有障碍,生成一个侧向躲避期望速度
    复杂版本需要:侧面多条探测射线,区分障碍物远近。