说明
已知:
-
在世界原点往 X 轴方向看去,ForwardVector 为 [ 1 , 0 , 0 ] [1,0,0] [1,0,0],此时的右手边的方向为 [ 0 , 1 , 0 ] [0,1,0] [0,1,0]
-
手柄摇杆、鼠标移动朝右得到的 [ 1 , 0 , 0 ] [1,0,0] [1,0,0],朝上得到的是 [ 0 , 1 , 0 ] [0,1,0] [0,1,0]
-
屏幕上,向右移动的输入为 [ 1 , 0 , 0 ] [1,0,0] [1,0,0],向下移动的输入为 [ 0 , 1 , 0 ] [0,1,0] [0,1,0]
-
对于旋转,Roll(X)的正方向为(右上左),Pitch(Y)的正方向为(后上前),Yaw(Z)的正方向为(左前右)
-
四元数
你会发现 X 轴 Y 轴变来变去,正的方向也变来变去,这到底是怎么回事?
我们讨论下 Z 方向:
- 在一个坐标系下,Z 轴正方向的单位向量为:X 轴正方向的单位向量叉乘 Y 轴正方向的单位向量,即 X ^ [ 1 , 0 , 0 ] × Y ^ [ 0 , 1 , 0 ] = Z ^ [ 0 , 0 , 1 ] \hat X[1,0,0]\times\hat Y[0,1,0]=\hat Z[0,0,1] X^[1,0,0]×Y^[0,1,0]=Z^[0,0,1]
- 根据左手螺旋还是右手螺旋,分为左手坐标系和右手坐标系,Unreal 采用的是左手坐标系,所以在世界内, Z ^ \hat Z Z^朝上的前提下,才会 X ^ \hat X X^ 朝前, Y ^ \hat Y Y^ 朝右
- 国内的数学习惯使用三维笛卡尔坐标系,为右手坐标系,也就是
X
^
\hat X
X^ 朝右,
Y
^
\hat Y
Y^ 朝前,
Z
^
\hat Z
Z^ 朝上
回看另外三个 Case:
- 基于左手坐标系,其实屏幕坐标是符合直觉的,也就是 X ^ × Y ^ \hat X\times\hat Y X^×Y^ 得出的向量朝屏幕(手机)上方
- 而手柄摇杆、鼠标的输入倒是比较符合右手坐标系,塞到左手坐标系下时,
Z
^
\hat Z
Z^ 其实是朝向下方的
- 猜测原因是:输入值由操作系统一路传过来,中间没有进行转换
- 旋转的三个方向,其实都是使用左手螺旋,即旋转前后向量叉乘,为旋转量对应的向量: V ⃗ × V ′ ⃗ = R . V e c t o r ( ) \vec V\times \vec{V'}=R.Vector() V×V′=R.Vector()
建议
在各个编程模块之间(其它信号转输入、输入信号处理、逻辑执行),尽可能让输入和输出满足以下要求:
- 必须满足左手坐标系
- 以下情况按照从前往后进行尝试:
- 按照世界坐标, Z ^ \hat Z Z^ 朝上(屏幕的上方、人物的头顶方向), X ^ \hat X X^ 朝前, Y ^ \hat Y Y^ 朝右
- 若
Z
^
\hat Z
Z^朝上时比较繁琐,则以屏幕坐标为准,
X
^
\hat X
X^ 朝右,
Y
^
\hat Y
Y^ 朝下,
Z
^
\hat Z
Z^ 朝后
- 有些人习惯第一象限落在右上方,可以旋转下Z轴,全局的标准则改为: X ^ \hat X X^ 朝上, Y ^ \hat Y Y^ 朝右, Z ^ \hat Z Z^ 朝后
举个例子:
在 EnhanceInput 内,输入和逻辑的中间层为 IA,我们讨论下 2D-Axis 的 IA,以 Gamepad Left Thumbstick 2D-Axis 映射到移动输入为例:
- 移动模块的输入 V ⃗ \vec V V, x = 1 x=1 x=1 表示前方有 1 的输入, y = 1 y=1 y=1 表示右方有 1 的输入
- 输入模块的输出,只需要加一个 Swizzle Input Axis Values 的 Modifier,Order 为 YXZ,即调换 X 和 Y 即可( [ i , j ] → [ j , i ] [i,j]\to[j,i] [i,j]→[j,i])
但是考虑下旋转镜头,Gamepad Right Thumbstick 2D-Axis 映射到旋转镜头输入:
- 旋转镜头比较特殊,因为按照FRotator的定义,右晃镜头为Z正,下晃镜头为Y正
- 用这个定义去强行转换,会涉及各种XYZ转换和正负问题,所以换一下,用CameraForwardVector在角色前方平面的落点位置为标准,采用屏幕坐标,这样就不用考虑Z的值了
- 旋转镜头模块的输入
V
⃗
\vec V
V,
x
=
1
x=1
x=1 表示方向为落点向右移动,为Yaw(Z)的正方向有 1 的输入
- y = 1 y=1 y=1 表示方向为落点向下移动,为Pitch(Y)的正方向有 1 的输入
- 输入模块的输出,只需要加一个 Negate,调转Y的朝向即可( [ i , j ] → [ i , − j ] [i,j]\to[i,-j] [i,j]→[i,−j])