Unity 第三人称 摄像机

今天主要是简单的模拟下吃鸡游戏的第三人称摄像机的实现。

观察

我们玩过吃鸡手游的都知道,吃鸡的人物跟随的摄像机有两种状态

1. 滑动屏幕的时候,摄像机左右上下移动,人物也会跟随着左右移动,上下抬头低头(播放相应的动画,但是不上下移动)。摄像机始终保持着观察人物背面。左右可以360度旋转,上下会有个最大值和最小值的限制,无法达到0度往上看或90度往下看。

2. 按住拖动右上角小眼睛按钮,摄像机左右上下移动,人物不会跟随着左右转动,头会左右上下摆动。几乎可以360度观察人物。上下左右的限制与情况1相同。

在不考虑头部转动的情况下,可以总结出两种情况摄像机的转动围绕人物的规则都是一样的,即以一个固定半径形成的球面上移动,除去了球面的最上和最下的部分,视角始终看向球心。而当滑动屏幕的情况下,人物也随之左右自转,保持摄像机观察人物的正背面。

分析

根据表现的现象,我们可以分析出我们需要实现的逻辑。我们可以想象人物的正后面有一条直线line,方向为(0,0,-1),摄像机离人物距离为distance,初始值摄像机的位置为(0,0,-distance)

当摄像机进行360度移动的时候,我们可以把移动操作拆分为两个步骤,首先是摄像机垂直移动,即以人物为中心,半径为distance的圆上移动。设垂直角度为α(0<min<α<max<90),则摄像机的高度y轴为distance*sin α,离人物的z轴距离为distance*cos α。此时摄像机的位置为(0,distance*sin α,-distance*cos α)

然后在之前的基础上,我们对摄像头进行水平移动,即以人物头顶高度distance*sin α的点为中心,半径为distance*cos α的圆上移动。设水平角度为β,则摄像机x轴为distance*cos α * sin β,z轴距离则更新为distance*cos α * cos β。

所以我们可以用两个角度α,β,来控制摄像机的转动,上下移动更新α值,左右移动更新β值,摄像机的位置为(distance*cos α * sin β, distance*sin α, -distance*cos α * cos β),摄像机始终看向(LookAt)人物

接着我们要区分两种情况的人物状态,当滑动屏幕的时候,人物会随之一起反方向转动,从而保证摄像机始终观察着人物背面。所以当摄像机水平转了β度时,人物的转向应该为(0, -β, 0)。而按住小眼睛的时候,人物不需要随之移动,但是当松开小眼睛的时候,摄像头需要回归原始位置,所以在按下的时候,我们需要纪录按下时摄像机的偏移角度,以供松开时复原。

实现

Demo中我们一共有四个cs文件,一个控制小眼睛按钮,一个控制屏幕滑动,一个控制人物移动,最后一个就是控制摄像机了。

还有需要搭建一个简单的测试场景,里面有一个方块模拟角色,一个plane做地面,然后添加一个UGUI的Button做小眼睛按钮。

首先是人物移动的控制器PlayerController,就是做了简单的位移

using UnityEngi
### Unity 中实现第三人称摄像机跟随的方法 在 Unity 中创建一个高效且易于使用的第三人称摄像机系统涉及多个方面,包括但不限于摄像机的位置更新、视角旋转以及响应用户的输入来调整距离。 #### 创建基础结构 对于第三人称摄像机的设计,采用一种分层架构有助于简化逻辑并提高灵活性。具体来说,通常会构建三个主要的游戏对象层次: - **FollowCamera**:负责处理整体位置跟踪目标角色。 - **Pivot (空物体)**:作为中间节点用于管理俯仰角(即绕 X 轴的旋转),它位于 `FollowCamera` 下方。 - **Main Camera**:实际渲染视图的部分,挂载于 Pivot 上面,仅需关注水平方向上的转向[^4]。 ```csharp // C# Code Example for setting up the hierarchy structure programmatically. public class ThirdPersonCameraSetup : MonoBehaviour { public GameObject player; void Start() { // Create an empty game object as a pivot point between camera and target var pivot = new GameObject("Pivot"); pivot.transform.SetParent(player.transform); // Reposition this script's owner, which should be Main Camera, under the newly created pivot transform.SetParent(pivot.transform); // Optionally set initial offsets here... } } ``` #### 处理摄像机运动与交互 为了让玩家能够自然地操控摄像机,需要编写脚本来监听键盘/鼠标的事件,并据此改变摄像机的角度和距离。下面是一个简单的例子展示了如何基于用户输入来进行这些操作[^2]。 ```csharp using UnityEngine; public class ThirdPersonCameraController : MonoBehaviour { private Transform _target; // The character to follow private float distanceFromTarget = 10f; // Distance from the target [Range(0.01f, 5)] public float rotationSpeed = 2f; [Range(0.01f, 5)] public float zoomSpeed = 2f; [Range(1, 20)] public float minDistance = 1f; [Range(1, 20)] public float maxDistance = 20f; void Update () { HandleRotation(); HandleZooming(); PositionUpdate(); } void HandleRotation(){ if(Input.GetMouseButton(1)){ float horizontalInput = Input.GetAxis("Mouse X") * rotationSpeed; float verticalInput = Input.GetAxis("Mouse Y") * rotationSpeed; Vector3 eulerAngle = transform.eulerAngles; eulerAngle.y += horizontalInput; eulerAngle.x -= verticalInput; eulerAngle.x = Mathf.Clamp(eulerAngle.x,-89f,89f); // Prevent flipping over transform.rotation = Quaternion.Euler(eulerAngle); } } void HandleZooming(){ float scrollValue = Input.mouseScrollDelta.y * Time.deltaTime * zoomSpeed; distanceFromTarget = Mathf.Clamp(distanceFromTarget - scrollValue,minDistance,maxDistance); } void PositionUpdate(){ Vector3 desiredPosition = _target.position - transform.forward * distanceFromTarget; transform.position = desiredPosition; } } ``` 此代码片段实现了基本的鼠标右键拖拽以旋转视角的功能,同时也支持通过滚动滚轮来动态调节摄像机到目标之间的相对距离[^1]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值