VR 100 天挑战第 63 天:在 Unity 中旋转向量并朝玩家朝向移动





5.00/5 (1投票)
如何在 Unity 中旋转向量并朝玩家朝向移动
引言
在之前的文章中,我们添加了一些简单的代码,允许我们的角色使用触摸板移动。很简单,没那么复杂。
现在,我们可能会发现一个问题,这取决于我们希望游戏中的移动如何工作。
我们可以很好地向前移动,但是当我们尝试在转身后移动我们的角色时会发生什么?
我们仍然会朝着相同的方向移动,无论我们从哪里开始!
对于玩家在我们的游戏中的玩法,有一些假设。玩家可以是
- 坐着,这样我们总是面对相同的方向
- 站着,这样他们可以在 360 度的角度转动,并且向前移动就是他们所看到的
我们的解决方案适用于第一种情况,但对于第二种情况,它不起作用。
在与这个问题斗争了很长时间后,我提出的解决方案是我们将不得不使用老式的数学和向量乘法!我们将学习如何旋转向量!
主要问题是,当我们更新我们的位置时,我们是根据持有摄像机的父游戏对象进行更新的,而不是根据我们所看的方向(主摄像机)。而且我们不能直接删除父容器,因为我们需要它来持有我们的摄像机。
我们必须做的是根据玩家所看的方向来旋转我们之前计算的向量。
添加基于玩家方向的移动
这花了很多时间来解决,但这是我们 TouchpadMovement
脚本的更新代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TouchpadMovement : MonoBehaviour
{
private float _speedSlowDown;
private Camera _mainCamera;
void Start()
{
_speedSlowDown = 0.1f;
_mainCamera = Camera.main;
}
void Update()
{
if (GvrControllerInput.IsTouching)
{
Vector2 touchPos = GvrControllerInput.TouchPos;
Vector3 movementVector = new Vector3(touchPos.x - 0.5f, 0,
touchPos.y - 0.5f); //adjust for center to be at 0.5, 0.5
Vector3 rotatedVector =
RotateVector(movementVector, _mainCamera.transform.eulerAngles.y);
transform.Translate(rotatedVector.x * _speedSlowDown, 0,
-rotatedVector.z * _speedSlowDown); // negative to adjust for the vector speed
}
}
// Given a direction and a degree,
// we'll rotate the direction vector by the given degree amount
private Vector3 RotateVector(Vector3 direction, float degree)
{
float radian = Mathf.Deg2Rad * degree; // convert our degree to be in radians
// calculate our rotation vector using matrix multiplication
// source: https://en.wikipedia.org/wiki/Rotation_matrix
float cos = Mathf.Cos(radian);
float sin = Mathf.Sin(radian);
float newX = direction.x * cos - direction.z * sin;
float newZ = direction.x * sin + direction.z * cos;
return new Vector3(newX, 0, newZ);
}
}
浏览代码
你不会相信我花了多少工夫才推导出这个公式!
尝试了很多次才弄对。我首先尝试使用 Quaternion.AngleAxis()
来计算旋转四元数以旋转我们的向量。但是,在玩了很长时间之后,结果并没有得到正确的值。
由于 Unity API 对我不起作用,我决定我别无选择,只能使用三角学来弄清楚我们如何旋转向量。结果在 RotateVector()
中。
理解 RotateVector()
我们试图解决的问题是,我们用来移动的向量是基于我们前进的方向,但是如果我们想朝着玩家所面对的方向移动,那么我们从触摸板创建的向量就不再正确了。
我们必须做的是旋转我们的向量,使“向前”成为我们主摄像机的前进方向。
我们目前拥有的信息是
- 我们的主摄像机所面对的角度
- 玩家输入移动向量
有了这些信息和我的高中毕业证书,我仍然不知道我应该怎么做!
我知道我必须对 Sin(X)
和 Cos(X)
做些什么,这已经是我记忆能帮我的极限了!
幸运的是,我们有互联网!特别是 Youtube!这个关于 旋转向量 的视频,讨论了我们如何计算旋转向量的新 X
和 Y
值,内容非常丰富。
维基百科 也有一个关于旋转矩阵来旋转我们的向量的很好的页面。
但是,TLDR 是这样的
X’ = X * Cos(radian) – Y * Sin(radian)
Y’ = X * Sin(radian) – Y * Cos(radian)
需要注意的是,将我们的角度转换为弧度很重要,查看 Mathf.Cos()
和 Mathf.Sin()
的文档
“返回角度 f(以弧度为单位)的余弦。”
我犯了一个错误,认为我们会传入角度,他们会给我们一个以弧度为单位的值……不……我犯了一个可怕的错误。这个函数的意思是给出一个转换为弧度形式的角度。
我如何确认这一点?谁还记得单位圆?
没错,我将这些值插入到 Unity 中,我发现我们必须将我们的度数转换为弧度。
回想起高中数学课,你的老师总是告诉你确保你处于度数模式。我让你失望了,老师!
总之。请随意尝试在 Unity 模拟器上使用该脚本。环顾四周,尝试通过按以下方式滑动您的触摸板:Shift + Ctrl + 鼠标移动。无论你面对哪个方向,我们现在都能够移动到正确的位置。
有了这个成就,我们就可以继续研究其他与游戏控制器交互的方式了!
结论
呼,这比我最初认为的移动所需的数学知识要多!
如果你曾经想过你是否需要编程的数学知识,这是一个例子(提示:不经常)。
现在,我们可以使用触摸板来移动我们的角色,但不仅如此,如果我们要在游戏中转过身来并移动,我们将朝着我们所看的方向移动。
完成此操作后,我们正式完成了移动。接下来,我们将研究如何使用我们的控制器拾取和投掷物体,以及如何使用我们的运动来投掷它!在下一篇文章中再见!