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

总结

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

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

相关推荐
Artistation Game14 小时前
九、怪物行为逻辑
游戏·unity·游戏引擎
百里香酚兰15 小时前
【AI学习笔记】基于Unity+DeepSeek开发的一些BUG记录&解决方案
人工智能·学习·unity·大模型·deepseek
妙为15 小时前
unreal engine5制作动作类游戏时,我们使用刀剑等武器攻击怪物或敌方单位时,发现攻击特效、伤害等没有触发
游戏·游戏引擎·虚幻·碰撞预设
dangoxiba17 小时前
[Unity Demo]从零开始制作空洞骑士Hollow Knight第十三集:制作小骑士的接触地刺复活机制以及完善地图的可交互对象
游戏·unity·visualstudio·c#·游戏引擎
先生沉默先1 天前
使用Materialize制作unity的贴图,Materialize的简单教程,Materialize学习日志
学习·unity·贴图
十画_8242 天前
Visual Studio 小技巧记录
unity·visual studio
red_redemption2 天前
cpp,git,unity学习
git·unity·游戏引擎
tealcwu2 天前
【Unity踩坑】Unity更新Google Play结算库
unity·游戏引擎
先生沉默先2 天前
unity 默认渲染管线材质球的材质通道,材质球的材质通道
unity·游戏引擎·材质
白鹭float.2 天前
【Unity AI】基于 WebSocket 和 讯飞星火大模型
人工智能·websocket·unity