Unity 中摄像机跟随的多种实现方法
在游戏开发中,摄像机的跟随效果对于提升玩家的游戏体验至关重要。在 Unity 中,我们可以通过多种方式实现摄像机的跟随。本文将详细介绍几种常见的摄像机跟随方法,包括第一人称摄像机跟随、第三人称摄像机跟随和固定相机跟随。
一、透视摄像机与正交摄像机
在 Unity 中,摄像机有两种主要类型:透视摄像机和正交摄像机。
透视摄像机(3D 多一些):透视摄像机模拟了人眼的视觉效果,具有近大远小的特点,适合用于 3D 游戏场景。它可以让玩家感受到深度和立体感,增强游戏的沉浸感。
正交摄像机(2D 多一些):正交摄像机没有近大远小的效果,所有物体在屏幕上的大小都是一致的。它通常用于 2D 游戏或需要精确控制物体大小和位置的场景。
二、Unity 摄像机的其他重要属性
1. 清除标记:
- 天空盒:可以取消默认天空,然后添加从商城购买的天空盒组件,为游戏场景营造出不同的氛围。
- 纯色:当摄像机拍摄不到的区域可以设置为纯色显示,这样可以避免出现黑色或其他不美观的背景。
- 仅深度:在多个相机融合的情况下,仅深度大的相机会成为主相机,拍摄不到的区域将不被显示。
2. 背景:在选择纯色清除标记时使用,可以设置特定的颜色作为背景。
3. 遮罩:与光源的遮罩类似,可以控制摄像机拍摄的对象范围。
4. 投影:用于选择相机类型,如透视投影或正交投影。
5. FOV 轴:类似于人眼的视野范围,影响着玩家在游戏中看到的画面大小。
6. 视野:相机有近面和远面,只有在这两个面之间的物体才会被显示。
7. 深度:在仅深度清除标记模式下使用,决定相机的显示优先级。
8. Viewport:摄像机在窗口中的显示位置,可以通过设置这个属性来实现分屏显示等效果。
9. 渲染路径:虽然不常用,但可以影响游戏的渲染性能和效果。
10. 目标纹理:修改后摄像机不在窗口显示,而是生成一个贴图文件,可以将这个贴图显示在任何物体上,实现特殊的效果。
11. 遮挡:不太常用,但可以用于控制摄像机对被遮挡物体的处理方式。
12. HDR:在打包时使用,可以提高游戏的画面质量和色彩动态范围。
13. MSAA:同样在打包时使用,可以减少图像的锯齿,提高画面的平滑度。
在 Unity 中实现摄像机跟随的方法有多种,以下是几种常见的方法:
一、第一人称摄像机跟随
这种跟随方式是以第一人称视角看向被跟随的对象,让玩家感觉自己就是游戏中的角色,一直显示对象的后背。
实现步骤:
- 创建一个
Camera
组件,将其赋值给target
变量,代表被跟随的对象。 - 创建一个
Transform
组件,将其赋值给this.transform.position
变量,代表摄像机的位置。 - 创建一个
Vector3
组件,将其赋值给offset
变量,用于设置摄像机与被跟随对象的相对位置。 - 在
FixedUpdate
方法中,通过target.position + offset
计算出相机的位置。 - 使用
Lerp
方法将相机的位置从当前位置过渡到计算出的位置,速度由Time.deltaTime
和speed
决定。其中speed
是一个自定义的速度参数,可以根据实际情况进行调整。 - 通过
Quaternion.LookRotation
方法获取旋转角度,再使用Slerp
方法将相机的旋转角度从当前角度过渡到计算出的角度,速度同样由Time.deltaTime
和speed
决定。
以下是示例代码:
using UnityEngine;
public class FirstPersonCameraFollower : MonoBehaviour
{
// 要跟随的相机对象
public Camera target;
// 当前物体的Transform组件,用于设置位置和旋转
public Transform thisTransform;
// 相机相对于目标的偏移量
public Vector3 offset;
// 跟随的速度
public float speed = 5f;
private void FixedUpdate()
{
// 计算目标位置加上偏移量得到相机应该到达的位置
Vector3 desiredPosition = target.position + offset;
// 使用线性插值(Lerp)方法将当前位置平滑过渡到目标位置,速度由时间差和speed决定
thisTransform.position = Vector3.Lerp(thisTransform.position, desiredPosition, Time.deltaTime * speed);
// 计算从当前位置指向目标位置的方向向量
Vector3 direction = target.position - thisTransform.position;
// 通过LookRotation方法获取从当前位置看向目标位置的旋转四元数
Quaternion desiredRotation = Quaternion.LookRotation(direction);
// 使用球形插值(Slerp)方法将当前旋转平滑过渡到目标旋转,速度由时间差和speed决定
thisTransform.rotation = Quaternion.Slerp(thisTransform.rotation, desiredRotation, Time.deltaTime * speed);
}
}
二、第三人称摄像机跟随
这种跟随方式是从第三人称视角看向被跟随的对象,让玩家可以看到角色的全貌。
实现步骤:
- 创建一个
Transform
组件,将其赋值给target
变量,代表被跟随的对象。 - 创建一个
Vector3
组件,将其赋值给disPos
变量,用于设置摄像机与被跟随对象的相对位置。 - 在
LateUpdate
方法中,通过target.position + Vector3.up * distanceUp - target.forward * distanceAway
计算出相机的位置,其中distanceUp
表示相机与目标的竖直高度参数,distanceAway
表示相机与目标的水平距离参数。 - 使用
Lerp
方法将相机的位置从当前位置过渡到计算出的位置,速度由Time.deltaTime
和smooth
决定。smooth
是一个自定义的平滑参数,可以控制摄像机跟随的平滑程度。 - 通过
LookAt
方法将相机的视角朝向目标的位置。
以下是示例代码:
using UnityEngine;
// 定义一个名为 ThirdPersonCameraFollower 的类
public class ThirdPersonCameraFollower : MonoBehaviour
{
// 要跟随的目标物体的 Transform
public Transform target;
// 自定义的相对位置向量
public Vector3 disPos;
// 相机与目标的竖直高度参数
public float distanceUp = 2f;
// 相机与目标的水平距离参数
public float distanceAway = 3f;
// 跟随的平滑度参数
public float smooth = 5f;
private void LateUpdate()
{
// 计算相机期望的位置,由目标位置加上竖直方向的偏移(Vector3.up * distanceUp)再减去目标正方向的偏移(target.forward * distanceAway)
Vector3 desiredPosition = target.position + Vector3.up * distanceUp - target.forward * distanceAway;
// 使用线性插值(Lerp)方法将当前相机位置平滑过渡到期望位置,插值速度由时间差(Time.deltaTime)和自定义的平滑度参数(smooth)决定
transform.position = Vector3.Lerp(transform.position, desiredPosition, Time.deltaTime * smooth);
// 让相机始终看向目标物体
transform.LookAt(target);
}
}
三、固定相机跟随
这种相机有一个参考对象,它会保持与该参考对象固定的位置,跟随该参考对象发生移动。
实现步骤:
- 创建一个
Transform
组件,将其赋值给target
变量,代表参考对象。 - 创建一个
Vector3
组件,将其赋值给offset
变量,用于设置摄像机与参考对象的相对位置。 - 在
FixedUpdate
方法中,通过target.position - offset
计算出相机的位置,其中offset
表示相机与目标的相对位置。
以下是示例代码:
using UnityEngine;
// 定义一个名为 FixedCameraFollower 的类
public class FixedCameraFollower : MonoBehaviour
{
// 要跟随的目标物体的 Transform
public Transform target;
// 相机相对于目标的偏移量
public Vector3 offset;
private void FixedUpdate()
{
// 计算相机的位置,通过目标位置减去偏移量来确定相机的位置
// 这样相机将始终保持与目标有一个固定的相对位置
transform.position = target.position - offset;
}
}