Unity的相机跟随和第三人称视角三
第三人称相机优化
介绍
之前相机视角讲过了两篇文章了,但是都是自动旋转视角,今天来了新需求,自动视角的时候,人没办法看全场上所有的景象,所以可以自己控制相机的视口方向,说白了就是做一个拖拽事件,再根据拖动的大小来控制相机视口旋转量,这样就完成了相机的可控视口旋转。
讲解
我上面的那个Gif可以看到,我创建了一个有拖动事件的UI,开始拖拽,拖拽中,结束拖拽。
在开始的时候我们采集他的开始拖拽点,然后在拖拽中进行插值运算计算进行镜头的左右旋转。
这个Gif里面我代码也加入了原来的人物中心点的位移,比如偏左一点或者偏右一点又或者是在正中心,这里我所使用的是Dotween这个插件,这里按键Q是切换镜头,ERT是镜头左侧,右侧,正中心的设置按键。
拖动事件
这里创建了一个UI来继承拖拽事件,可以把这个UI的透明通道调整到看不到的程度,我这里是为了大家方便看到我没有设置为0。
MoveTouch.cs
csharp
using UnityEngine;
using UnityEngine.EventSystems;
public class MoveTouchTest : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
/// <summary>
/// 跟随相机
/// </summary>
public FollowCameraTest followCameraTest;
/// <summary>
/// 是否在拖拽中
/// </summary>
public bool IsDrag = false;
/// <summary>
/// 开始位置
/// </summary>
private float startPosX;
/// <summary>
/// 旋转的角度
/// </summary>
public float angle = 1;
public void OnBeginDrag(PointerEventData eventData)
{
IsDrag = true;
startPosX = eventData.position.x;
}
public void OnDrag(PointerEventData eventData)
{
if (!followCameraTest.IsHasBall) return;
if (!IsDrag) return;
followCameraTest.transform.localEulerAngles += new Vector3(0, (eventData.position.x - startPosX) * angle, 0);
startPosX = eventData.position.x;
}
public void OnEndDrag(PointerEventData eventData)
{
IsDrag = false;
}
private void OnEnable()
{
IsDrag = false;
}
private void OnDisable()
{
IsDrag = false;
}
}
相机逻辑
我用电脑测试的所以下面代码加了个鼠标滚轮控制镜头的旋转。
FollowCameraTest .cs
csharp
using DG.Tweening;
using Unity.VisualScripting;
using UnityEngine;
public class FollowCameraTest : MonoBehaviour
{
public Transform target; // 要跟随的目标对象
public Transform football; // 其次要跟随的目标
public Vector3 camPosOffset = new Vector3(0, 1.5f, -5); // 相机与目标之间的距离偏移量
public Vector3 camEulerOffset = new Vector3(6, 0, 0); // 相机与目标之间的距离偏移量
public float smoothSpeed = 0.05f; // 相机跟随平滑度
public float rotateSpeed = 0.08f; // 相机旋转平滑度
public float fov = 45;
public bool IsHasBall = true;
public Camera m_cam;
public float moveTime = 1f;
public float angle = 5;
private void Start()
{
m_cam.transform.localPosition = camPosOffset;
m_cam.transform.localEulerAngles = camEulerOffset;
transform.position = target.transform.position;
m_cam.fieldOfView = fov;
}
public void LateUpdate()
{
if (target == null) return;
if (Input.GetKeyDown(KeyCode.Q))
{
IsHasBall = !IsHasBall;
}
if (Input.GetKeyDown(KeyCode.E))
{
if (m_cam != null) m_cam.transform.DOLocalMoveX(-1, moveTime);
}
if (Input.GetKeyDown(KeyCode.R))
{
if (m_cam != null) m_cam.transform.DOLocalMoveX(1, moveTime);
}
if (Input.GetKeyDown(KeyCode.T))
{
if (m_cam != null) m_cam.transform.DOLocalMoveX(0, moveTime);
}
//相机缓动过程
transform.position = Vector3.Lerp(transform.position, target.transform.position, smoothSpeed);
if (IsHasBall)
{
//这里我用的电脑方便测试加了一个滚轮的方式去旋转镜头,需要可以打开 不需要就不用管
//float mouseWheel = Input.GetAxis("Mouse ScrollWheel");
//transform.localEulerAngles += mouseWheel * angle * Vector3.up;
}
else
{
Vector3 tar = ((target.position + football.position) * 0.5f - target.transform.position).normalized;
tar.y = 0;
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(tar), rotateSpeed);
}
}
}
人物移动逻辑
RoleCtrlTest.cs
csharp
using UnityEngine;
public class RoleCtrlTest : MonoBehaviour
{
public float moveSpeed = 5f; // 人物移动速度
public float rotateSpeed = 5f;
public FollowCameraTest followCamera;
void Update()
{
Vector3 moveDir = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDir = RotateRound(moveDir, Vector3.zero, Vector3.up, followCamera.transform.localEulerAngles.y);
if (followCamera.IsHasBall)
{
transform.position += moveDir * moveSpeed * Time.deltaTime;
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(moveDir), rotateSpeed);
}
else
{
if (moveDir == Vector3.zero) return;
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(moveDir), rotateSpeed);
transform.position += transform.forward * moveSpeed * Time.deltaTime;
}
}
protected Vector3 RotateRound(Vector3 position, Vector3 center, Vector3 axis, float angle)
{
Vector3 point = Quaternion.AngleAxis(angle, axis) * (position - center);
Vector3 resultVec3 = center + point;
return resultVec3;
}
}
总结
对比之前自动旋转的,这个版我觉着会更舒服一些,因为这个版的镜头更加可控制一些,但是这个也会让你操作变得复杂,无疑增加了一种操作负担。