比起传统的镜头跟随,我更喜欢一种镜头 - 玩家在一定的范围里移动,镜头位置保持不变,当玩家超出该移动范围,则镜头开始追随玩家,直到玩家再次出现在限定的范围里。

点击 Main Camera 打开摄像头的 Inspector 界面,我们添加一个自定义脚本,命名为:CameraMotor,创建方法和创建 Player 脚本是一样的。然后我们将 Project 面板里的 CameraMotor 文件拖拽到 Scripts 文件夹里。

双击用 Visual Studio 打开 CameraMotor 源文件

删掉所有在 CameraMotor 类里面的函数(Start 和 Update),然后 ctrl + shift + m 打开 Unity 函数库,找到 LateUpdate 函数,点击添加。该函数在 Update 和 FixedUpdate 之后才被调用。因为我们需要在逻辑上让玩家先移动,镜头才跟随。这样不会让玩家产生奇怪的视觉效果。

在代码里,我们需要镜头跟随一个目标,所以我声明一个变量 public Transform lookAt; 将其修饰符写为 public,以便我们可以在 Inspector 面板中访问它。

然后我们再定义两个 float 类型的数据 bound。这将用作规定摄像机允许玩家行走且不移动摄像头的边界。

然后在刚刚添加的 FixedUpdate 函数里开始编程:

我们需要记录两个帧之间距离的差距,一开始声明一个 Vector3 类型数据 delta,值为 0 (Vector3.zero)。然后我们需要检测目标是否碰到边界,如果碰到边界则移动目标。我们用目标的位置减去相机的位置(计算目标位置和中心点的距离),如果目标超出边界,则开始移动镜头

我们用 transform.position.x < lookAt.position.x 来判断目标在焦点的右侧;反之(else)就在左侧。在右侧的话,就要修改 delta.x(也就是函数一开始我们定义的位移)为计算出来的边界位移减去边界。

当修改完 x y 轴,我们就可以移动镜头了。用 transform.position 获取当前 GameObject(也就是摄像机的位置)然后赋值为:transform.position + new Vector3(delta.x, delta.y, 0); 注意,这里的变量是 delta.x 而不是 deltaX

最后一个参数(z 轴)为 0 是因为我们不能移动镜头的高度。解释:虽然是 2D 游戏,但是镜头 z 轴的位置位于角色以及地板等精灵图的 10 个单位。这就好比你的桌子上有一张纸,然后你要拍摄这张纸,需要在比纸高一点的地方,才能拍到纸上的内容。这里就有小伙伴要问了,为什么修改摄像机 z 轴的值,没有近大远小的效果?这是因为一开始我们创建项目的时候,对摄像机的模式定义为 Orthographic(正交视图),因此不会有透视效果。

完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraMotor : MonoBehaviour
{
public Transform lookAt; // 镜头需要聚焦的目标
public float boundX = 0.15f; // 角色能够离开中心的最大距离
public float boundY = 0.05f; // 上下轴

// 在 Update 和 FixedUpdate 之后才被调用。因为玩家先移动,镜头才跟随
private void LateUpdate()
{
Vector3 delta = Vector3.zero; // 记录两个帧之间的距离

// 检测目标是否在 x 轴的边界里。
float deltaX = lookAt.position.x - transform.position.x; // 目标的位置 - 相机的位置
if (deltaX > boundX || deltaX < -boundX) // 判断如果出界
{
if (transform.position.x < lookAt.position.x) // 目标在焦点的右侧
{
delta.x = deltaX - boundX;
}
else // 目标在焦点的右侧
{
delta.x = deltaX + boundX;
}
}

// 检测目标是否在 y 轴的边界里
float deltaY = lookAt.position.y - transform.position.y;
if (deltaY > boundY || deltaY < -boundY)
{
if (transform.position.y < lookAt.position.y) // 目标在焦点的上方
{
delta.y = deltaY - boundY;
}
else // 目标在焦点的下方
{
delta.y = deltaY + boundY;
}
}

// 移动镜头
transform.position += new Vector3(delta.x, delta.y, 0);
}
}

回到 Unity,很关键的一步,我们需要先在 Hierarchy 面板点击 Main Camera,然后确保它的 Inspector 面板中,我们刚刚写的代码元件已经被加载完毕,加载完毕的效果如右图所示。

然后我们回到 Hierarchy 面板,直接长按(千万别点击,直接长按!) player_0 然后拖曳到 CameraMotor 元件中的 Look At 属性。这样就可以给摄像机设置目标(为玩家)了。你也可以通过修改 Bound X 和 Y 来调整玩家可以移动的边距。

接下来,点击 ▶ 即可测试你的玩家是否在移动的时候被镜头跟随了。可以试试调整边界值来观察变化

那这篇文章到这里结束啦!喜欢我的视频的小伙伴记得在我们的官网注册账号,以获得更多福利哦!我们下个文章再见啦~