Unity 原神人物移动和镜头处理

文章详细讨论了在游戏开发中如何避免使用SetTrigger进行人物移动,推荐使用float进行平滑控制。介绍了原神的镜头界面,以及人物移动与视角控制的关系,特别提到了Cinemachine和LeanTouch插件在镜头动态改变及捏合缩放中的应用。此外,还分享了关于镜头恢复速度(Damping)和镜头偏移的设置技巧。
摘要由CSDN通过智能技术生成

每帧都处理的地方 不要用 SetTrigger
为什么呢?
你肯定会希望 SetTrigger run 就跑步 SetTrigger stop 就停止
但事实并非如此
SetTrigger 会在下一帧自动设置回去
而你移动肯定是每帧都在 SetTrigger 所以人物移动会抽搐
最好的办法是 设置float

分析原神的镜头
界面左侧负责控制人物移动
界面右侧负责控制视角
人物的移动方向 和 人物朝向没有关系。只和镜头方向有关系。

v.x = this.joystick.Horizontal;
v.z = this.joystick.Vertical;
if (v.x == 0 && v.z == 0)
{
    this.animator.SetFloat("runfloat", 0.0f);
    return;
}
else
{
    this.animator.SetFloat("runfloat", 0.2f);
}
Vector3 startV3 = new Vector3(this.freeLook.transform.position.x, 0, this.freeLook.transform.position.z);
Vector3 endV3 = new Vector3(this.transform.position.x, 0, this.transform.position.z);
Vector3 n = (endV3 - startV3).normalized;
镜头到角色的方向
this.transform.forward = n;
临时让人物朝向这个方向,方便后面计算
Vector3 v3 = this.transform.forward * v.z + this.transform.right * v.x;
前方向 * 摇杆的 y + 右方向 * 摇杆的 x
this.transform.LookAt(this.transform.position + v3);
this.transform.position += v3 * 0.03f;

右边的镜头用的是freelook镜头
ps.本来想计算角度啥的
后来志神提醒一下就解决了 感谢志神!

一点优化小细节
Vector3.sqrMagnitude 是指长度的平方,也就是Vector3.magnitude的平方

计算向量大小的平方会比计算向量的大小要快很多,因为向量的大小由勾股定理得出,所以有开方操作,如果只是单纯的比较两个向量的大小,可以使用sqrMagnitude会快很多。

镜头让障碍物挡住了咋整?
在这里插入图片描述
添加一个这个
在这里插入图片描述
这三个就是遇到障碍物 不同的处理方式

第一个 就是简单的把 镜头移动到障碍物前面 向着镜头的 Forward 方向移动
第二个 是保持镜头高度 也就是说 距离障碍物越近 人物变的越大
第三个 保持镜头距离 但是会改变角度 相当于把摄像头挤上去了

可以看这个地方
https://cloud.tencent.com/developer/article/2080742
总之非常重要的功能

如果左右移动 你会发现 角色是绕圈的
因为你的移动方向和镜头是90度 相当于画圈了

可以参考下这个
在这里插入图片描述
Lock To Target On Assign:本地空间,相机被激活或target赋值时的相对位置。
Lock To Target With World Up:本地空间,保持相机y轴朝上,yaw和roll为0。
Lock To Target No Roll:本地空间,锁定到目标物体,roll为0。
Lock To Target:本地空间,锁定到目标物体
World Space:世界空间
Simple Follow With World Up:相对于目标的位置,使用相机的本地坐标系,保持相机y轴朝上

获得组件用 GetCinemachineComponent

这个插件还有一个例子可以学习下
在这里插入图片描述

仔细观察
原神双指捏合 可以控制镜头
怎么办
非常简单
控制freelook镜头的地方 判断下 如果是两指就不滑动屏幕了

if (JoyCube.Use.UpdateAndGetFingers().Count == 2)
{
    return;
}

下面是动态改变
在这里插入图片描述

var fingers = Use.UpdateAndGetFingers();
Cinemachine.CinemachineFreeLook.Orbit o = this.freeLook.m_Orbits[1];
o.m_Radius *= Lean.Touch.LeanGesture.GetPinchScale(fingers);  
Cinemachine.CinemachineFreeLook.Orbit o1 = new Cinemachine.CinemachineFreeLook.Orbit(o.m_Height, o.m_Radius);
this.freeLook.m_Orbits[1] = o1;

直接改属性是不行的 需要创建新的 Orbit 并赋值回去 不然不起作用
好 现在就实现了原神的基本镜头了

对了 捏合状态用的插件是 Lean Touch
非常方便的插件
判断捏合只需要几句话

public static Lean.Touch.LeanFingerFilter Use = new Lean.Touch.LeanFingerFilter(true);
var fingers = Use.UpdateAndGetFingers();
LeanGesture.GetPinchScale(fingers)

滑动屏幕大概是这样的 (草稿)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TouchTest : MonoBehaviour
{
    public Cinemachine.CinemachineFreeLook look;
    private bool drag = false;
    private float startY = 0;
    // Update is called once per frame
    private float lastx = 0;
    private float lasty = 0;

    void Update()
    {
        if (JoyCube.Use.UpdateAndGetFingers().Count == 2)
        {
            return;
        }
 
        if (this.isClick())
        {
            this.drag = true;
            this.startY = look.m_YAxis.Value;
            this.lasty = Input.mousePosition.y;
            this.lastx = Input.mousePosition.x / Screen.width;
        }
        if (Input.GetMouseButtonUp(0))
        {
            this.drag = false;
        }
        if (this.drag)
        {
            float pery = (this.lasty - Input.mousePosition.y) / Screen.height;
            look.m_YAxis.Value = this.startY + pery;
            float perx = Input.mousePosition.x / Screen.width;
            look.m_XAxis.Value = -360.0f * (this.lastx - perx);
            this.lastx = perx;
        }
    }

    private bool isClick()
    {
        if (Input.GetMouseButtonDown(0))
        {
            if (UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject())
            {
                // Debug.Log("点到了ui");
                return false;
            }
            return true;
        }
        if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
        {
            if (UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
            {
                Debug.Log("Touched the UI");
            }
        }
        return false;
    }
}

在这里插入图片描述
Damping 是干啥的呢
这是控制镜头恢复的速度
如果是0 那么镜头就立即移动
数值越大 镜头恢复越慢

在这里插入图片描述

在这里插入图片描述
这个是控制镜头偏移的 好像越肩视角用这个

在这里插入图片描述
镜头阻尼

选择这个会显示辅助线
在这里插入图片描述
在这里插入图片描述
但是 你必须展开 Aim , 不然他不会起作用。

在这里插入图片描述
细心的你 一定会发现 X Axis 的 value 永远是0
原神那种 一上来 角度固定在后背的 根本做不到
这是为啥呢?
在这里插入图片描述
官方给出了答案

在这里插入图片描述
就是你的binding mode 需要换一下

你会发现 上面的界面改变了
在这里插入图片描述
这样你就可以设置value了

还有一个功能 需要一键回归角度
在这里插入图片描述

y的value 非常有意思
0就是bottom 0.5就是middle 1就是top
和你设置的height没关系
你middle再高 也是0.5
在这里插入图片描述
推荐一个林大的博客
https://blog.csdn.net/linxinfa/article/details/124537415
无敌了

一般用 在这里插入图片描述
然后这个有一个特点 就是一开始镜头的位置是相对固定的
所以一开始的时候 要让player的rotation是0
这样 look free的 m_XAxis 的 0 和 rotation的0 是 同样的方向
方便我们后面做reset镜头

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值