每帧都处理的地方 不要用 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镜头