巡逻与追逐
本课属于 Coddy Unity 学习旅程的“物理与游戏玩法”单元。第 54 课,共 71 课。
巡逻中的守卫会沿着路线行走,直到发现玩家,然后追赶玩家;玩家离开后,它会回到路线。两种行为的转向方式相同,都是朝着某个点移动,所以可以用一个方法来完成两种行走行为。这个哨兵会在两个岗哨之间来回移动,并在玩家进入 chaseRange 范围时追赶玩家:
[SerializeField] private Transform pointA;
[SerializeField] private Transform pointB;
[SerializeField] private Transform player;
[SerializeField] private float speed = 2f;
[SerializeField] private float chaseRange = 5f;
private Rigidbody rb;
private Transform goal;
void Start()
{
rb = GetComponent<Rigidbody>();
goal = pointA;
}
void FixedUpdate()
{
if (Flat(player.position - rb.position).magnitude < chaseRange)
{
WalkTo(player.position);
return;
}
if (Flat(goal.position - rb.position).magnitude < 0.2f)
{
goal = goal == pointA ? pointB : pointA;
}
WalkTo(goal.position);
}
void WalkTo(Vector3 target)
{
Vector3 dir = Flat(target - rb.position).normalized;
rb.linearVelocity = new Vector3(dir.x * speed, rb.linearVelocity.y, dir.z * speed);
}
Vector3 Flat(Vector3 v)
{
return new Vector3(v.x, 0f, v.z);
}先检查是否需要追赶,return 会跳过巡逻代码,因此只要玩家靠近,追赶行为就会优先执行。goal 是一个字段,所以哨兵会在追赶期间记住目标:玩家离开后,它会继续前往原本要去的岗哨。
抵达检测会测量地面上的距离。岗哨是地面上的标记,而哨兵的中心比标记高 1 个单位,所以如果把高度也算进距离,距离就永远不会小于 1,哨兵也就永远不会掉头。检测条件是距离小于 0.2,而不是刚好等于 0:哨兵每秒移动 2 个单位,每步会移动 0.04 个单位,因此几乎不会刚好停在岗哨上。
挑战
中等让机器人沿着航点巡逻,并追逐靠近的玩家。
- 编写
WalkTo(Vector3 target),让rb.linearVelocity在地面上朝目标移动,速度为speed,同时保持 y 方向的速度。 - 在
FixedUpdate()中,当玩家距离小于chaseRange时,调用WalkTo(player.position)并执行return。 - 否则,当距离
waypoints[next]小于 0.2 时,设置next = (next + 1) % waypoints.Length;,然后朝waypoints[next]移动。
按下“开始”,然后穿过它的路径。接着按“检查”。
亲手试试
using UnityEngine;
public class Robot : MonoBehaviour
{
[SerializeField] private Transform[] waypoints;
[SerializeField] private Transform player;
[SerializeField] private float speed = 4f;
[SerializeField] private float chaseRange = 4f;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
// 玩家靠近时追逐玩家,否则沿巡逻路线移动
}
}
物理与游戏玩法中的所有课
自己练习: Unity 在线编辑器