Unity的相机跟随和第三人称视角二
展示
我录的视频上可能看不太出来,但是其实今天的这个方法比原来写的那个方法更简便并且死角更少一些。
这里我也做了两个人物偏移的视角,按Q是原来的两个相机模式切换,按E、R、T是人物在相机中心的偏移。
介绍
之前讲过一个第三人称的相机镜头,今天想把原来的镜头改一下。之前测试的时候发现了原来相机的镜头移动是有点问题的,虽然都是平滑的移动但是其实不是环形移动。
Unity的相机跟随和第三人称视角一
第一篇的相机的移动我下面举个例子大家看一下,这里虽然都是平滑的移动,但是还是有差距的。
第一篇文章中相机的平滑大家可以看到其实是A->B->C->D->A都是直接取的两个点进行平滑的移动,并且在移动的过程中相机还要进行旋转,所以说实际上移动的并不是球型移动(用我第一篇的相机你会发现有的时候视角切换的时候很难看清楚人有的时候)。后面我会讲一个更简单一点的相机移动和旋转跟随人物。
第二种相机模式远离
这种相机其实就是让相机一直缓慢的跟着人物,然后旋转的话是直接调整玩家的旋转。下面我在画图说明一下。
这种方式其实就是按照这个球型来进行移动和旋转,这样就避免了一些相机的死角问题。
这里的搭建跟第一种搭建其实是一样的
代码
这里我直接上代码了,原理也很简单,比之前写的那个镜头移动的还要更简单一些。
FollowCameraTest.cs
csharp
using DG.Tweening;
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;
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)
{
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(target.transform.forward), rotateSpeed);
}
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 rotationSpeed = 180f; // 人物转向速度
public float rotateSpeed = 5f;
public FollowCameraTest followCamera;
void Update()
{
if (followCamera.IsHasBall)
{
// 获取玩家的输入
float moveHorizontal = Input.GetAxis("Horizontal");
if (moveHorizontal == 0)
{
}
else if (moveHorizontal > 0)
{
transform.Rotate(Vector3.up, rotationSpeed * Time.deltaTime);
}
else if (moveHorizontal < 0)
{
transform.Rotate(Vector3.up, -rotationSpeed * Time.deltaTime);
}
if (Input.GetAxis("Vertical") > 0)
{
transform.position += followCamera.transform.forward * moveSpeed * Time.deltaTime;
}
}
else
{
Vector3 moveDir = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
if (moveDir == Vector3.zero) return;
moveDir = RotateRound(moveDir, Vector3.zero, Vector3.up, followCamera.transform.localEulerAngles.y);
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;
}
}
总结
这种方式比原来的代码量还要少,并且死角也少了很多。
如果大家还有什么好的想法可以跟我探讨,感谢大家的支持!