Unity的滑动控制相机跟随和第三人称视角三

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

第三人称相机优化

Unity第三人称相机视角一
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;
    }
}

总结

对比之前自动旋转的,这个版我觉着会更舒服一些,因为这个版的镜头更加可控制一些,但是这个也会让你操作变得复杂,无疑增加了一种操作负担。

相关推荐
WarPigs9 小时前
游戏签到系统
unity
小拉达不是臭老鼠12 小时前
Unity中的UI系统之UGUI
学习·ui·unity
万兴丶12 小时前
Coplay适用于 Unity 的“Al 代理”使用指南
unity·游戏引擎·ai编程
魔士于安15 小时前
Unity材质球大合集
unity·游戏引擎·材质
mxwin16 小时前
Unity Shader 冰面 Shader 制作原理与流程
unity·游戏引擎·shader
玖玥拾17 小时前
Cocos学习笔记:关卡系统、音频管理与物理控制
游戏引擎·cocos2d
小拉达不是臭老鼠18 小时前
Unity中的UI系统之UGUI_登陆面板实现
ui·unity
郝学胜-神的一滴18 小时前
[简化版 GAMES 101] 计算机图形学 11:频域·卷积·抗锯齿
c++·unity·图形渲染·opengl·three·unreal
玖玥拾1 天前
Cocos学习笔记:滚动视图、关卡系统与本地存储
游戏引擎·cocos2d
元气少女小圆丶1 天前
SenseGlove Nova 2+Unity开发笔记2
笔记·unity·游戏引擎