运行效果
摄像机运行效果如下所示。
玩家角色
首先创建一个可用的玩家角色,写好移动逻辑,如果要使用在Unity商店中购买的资源,可以点击Window菜单栏> Package Manager选项,来打开Package Manager窗口,如下所示,然后下载你需要的资源。
如果你没有在资源商店的精灵资产,可以在Hierarchy视图,右键单击,选择“2D Object" > “Sprites” > “Capsule”。
这将会在场景中创建一个2D胶囊体,我们就用这个胶囊体来充当我们的玩家角色,如下图所示。
脚本
新建一个脚本,名叫FollowCamera,然后将该脚本挂载到Camera上。
字段
我们要创建的跟随摄像机具有平滑移动的功能,所以我们需要创建两个字段,一个字段用于表示跟随的物体,一个字段用于表示摄像机移动的平滑程度。
声明一个Transform类变量target,用于指定摄像机要跟随的目标物体,注意要声明成public的,这样我们可以在编辑器中将目标物体赋值给该变量。
声明一个float类型变量damping,用于指定跟随的平滑程度,数值越大表示跟随越平滑,默认值赋值为1。
public Transform target; // 跟随的目标物体
public float damping = 1; // 跟随的平滑程度
跟随逻辑
跟随逻辑的代码我们放在LateUpdate() 方法中实现,这个方法在每一帧最后被调用。
private void LateUpdate()
{
}
在LateUpdate() 方法中,首先判断目标物体是否存在(是否已经赋值给target变量),如果没有目标物体,不进行任何操作,避免报错。
if (target != null)
{
}
接下来计算摄像机应该移动的向量:
// 计算目标位置在屏幕上的坐标
Vector3 targetPosition = Camera.main.WorldToViewportPoint(target.position);
// 计算摄像机应该移动的向量
Vector3 delta = target.position - Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, targetPosition.z));
首先,使用Camera.main.WorldToViewportPoint()方法将目标物体的位置转换为视口坐标(相对于摄像机的屏幕视图比例)。
然后,通过计算delta向量,获得目标物体在视口坐标系下的中心位置与屏幕中心位置之间的偏移量。使用Camera.main.ViewportToWorldPoint()方法将偏移量转换为世界坐标系下的偏移量。
接下来计算目标位置和移动摄像机。
// 计算摄像机的目标位置
Vector3 destination = transform.position + delta;
// 使用平滑阻尼移动摄像机
transform.position = Vector3.Lerp(transform.position, destination, damping * Time.deltaTime);
根据计算得到的摄像机的目标位置,使用Vector3.Lerp()方法以平滑阻尼的方式将摄像机移动到目标位置。
这样脚本就写好了。可以使摄像机平滑地跟随目标物体,并保持目标物体在摄像机的中心位置。通过调整damping变量的值,我们还可以控制跟随的平滑程度。
完整代码
using UnityEngine;
public class FollowCamera: MonoBehaviour
{
public Transform target; // 跟随的目标物体
public float damping = 1; // 跟随的平滑程度
private void LateUpdate()
{
if (target != null)
{
// 计算目标位置在屏幕上的坐标
Vector3 targetPosition = Camera.main.WorldToViewportPoint(target.position);
// 计算摄像机应该移动的向量
Vector3 delta = target.position - Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, targetPosition.z));
// 计算摄像机的目标位置
Vector3 destination = transform.position + delta;
// 使用平滑阻尼移动摄像机
transform.position = Vector3.Lerp(transform.position, destination, damping * Time.deltaTime);
}
}
}