Unity的相机跟随和第三人称视角二

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;
    }
}

总结

这种方式比原来的代码量还要少,并且死角也少了很多。

如果大家还有什么好的想法可以跟我探讨,感谢大家的支持!

相关推荐
旧物有情18 小时前
游戏开发常用架构 #MVP,MVC
游戏·unity·架构·mvc
勇踏前人未索之境20 小时前
Unity打包运行于鸿蒙手机
unity·智能手机·harmonyos
玖玥拾21 小时前
Unity 3D 笔记(十一)UI 框架进阶:栈弹窗交互、BasePanel 基类虚方法、DoTween 界面动画
笔记·3d·unity
郝学胜-神的一滴1 天前
中级OpenGL教程 023:Assimp模型加载全解——从源码到架构的骈文探秘
c++·unity·游戏引擎·cmake·unreal engine·opengl
xcLeigh2 天前
Unity基础:GameObject与Component——Unity核心架构思想彻底理解
unity·教程·component·gameobject
郝学胜-神的一滴2 天前
中级OpenGL教程 022:探秘三维世界的血脉传承——物体父子关系与矩阵递归奥义
c++·线性代数·unity·矩阵·游戏引擎·unreal engine·opengl
weixin_424294673 天前
Unity的测试Edit Mode和Play Mode,有什么区别?
unity
Python私教3 天前
我用 AI 做出了第一个 Godot 贪吃蛇
人工智能·游戏引擎·godot
玖玥拾3 天前
Unity 3D 笔记(八)ScrollRect 滚动视图、NavMesh 自动寻路系统
笔记·3d·unity