準備
UnityVRテンプレートから超簡単にワールド内を移動できるようになります。
検証エディタ:Unity2021.1
UnityHubで新しいプロジェクトを作る際にテンプレート「VR」を選択して作成。
プロジェクト設定のXRPluginManagementでOculusをチェック
以下のスクリプトを適当にアセットフォルダに作成します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
public class VR_Input : MonoBehaviour
{
public enum InputVRBool { Primary, Secondary, Trigger, Grip, Menu, PrimaryAxis };
public enum InputVRFloat { Trigger, Grip };
public static bool GetPresseButton(XRNode node, InputVRBool inputVRBool)
{
bool value = false;
var inputdevice = new List<InputDevice>();
InputDevices.GetDevicesAtXRNode(node, inputdevice);
if (0 < inputdevice.Count)
{
foreach (var device in inputdevice)
{
switch (inputVRBool)
{
case InputVRBool.Trigger: device.TryGetFeatureValue(CommonUsages.triggerButton, out value); break;
case InputVRBool.Grip: device.TryGetFeatureValue(CommonUsages.gripButton, out value); break;
case InputVRBool.Primary: device.TryGetFeatureValue(CommonUsages.primaryButton, out value); break;
case InputVRBool.Secondary: device.TryGetFeatureValue(CommonUsages.secondaryButton, out value); break;
case InputVRBool.PrimaryAxis: device.TryGetFeatureValue(CommonUsages.primary2DAxisClick, out value); break;
case InputVRBool.Menu:
if (node == XRNode.LeftHand)
{
device.TryGetFeatureValue(CommonUsages.menuButton, out value);
}
break;
}
}
}
return value;
}
public static float GetAxis1D(XRNode node, InputVRFloat inputVRFloat)
{
float value = 0;
var inputdevice = new List<InputDevice>();
InputDevices.GetDevicesAtXRNode(node, inputdevice);
if (0 < inputdevice.Count)
{
foreach (var device in inputdevice)
{
switch (inputVRFloat)
{
case InputVRFloat.Trigger: device.TryGetFeatureValue(CommonUsages.trigger, out value); break;
case InputVRFloat.Grip: device.TryGetFeatureValue(CommonUsages.grip, out value); break;
}
}
}
return value;
}
public static Vector2 GetAxis2D(XRNode node)
{
Vector2 value = Vector2.zero;
var inputdevice = new List<InputDevice>();
InputDevices.GetDevicesAtXRNode(node, inputdevice);
if (0 < inputdevice.Count)
{
foreach (var device in inputdevice)
{
device.TryGetFeatureValue(CommonUsages.primary2DAxis, out value);
}
}
return value;
}
public static void Recenter()
{
var inputdevice = new List<InputDevice>();
InputDevices.GetDevicesAtXRNode(XRNode.CenterEye, inputdevice);
if (0 < inputdevice.Count)
{
foreach (var device in inputdevice)
{
device.subsystem.TryRecenter();
}
}
}
}
次に、以下のスクリプトを作成、サンプルシーンにある「XRRig」というオブジェクトにくっつけます。
using UnityEngine;
[RequireComponent(typeof(CharacterController))]
public class VR_BasicController : MonoBehaviour
{
private CharacterController cc;
[SerializeField] private float speed = 2;
[SerializeField] private int angle = 30;
private bool RT, LT;
private Vector2 stickL;
private Vector2 stickR;
private float gravity = 20;//9.81f;
void Start()
{
cc = GetComponent<CharacterController>();
VR_Input.Recenter();
}
void Update()
{
stickL = VR_Input.GetAxis2D(UnityEngine.XR.XRNode.LeftHand);
stickR = VR_Input.GetAxis2D(UnityEngine.XR.XRNode.RightHand);
Move();
Rotate();
if (VR_Input.GetPresseButton(UnityEngine.XR.XRNode.RightHand, VR_Input.InputVRBool.PrimaryAxis))
{
VR_Input.Recenter();
}
}
void Move()
{
cc.enabled = true;
Vector3 direction = new Vector3(stickL.x, 0, stickL.y);
Vector3 velocity = direction * speed;
velocity.y -= gravity;
velocity = transform.TransformDirection(velocity);
cc.Move(velocity * Time.deltaTime);
}
void Rotate()
{
if (stickR.x < -0.25f && !LT)
{
LT = true;
transform.Rotate(0, -angle, 0);
}
if (0.25f < stickR.x && !RT)
{
RT = true;
transform.Rotate(0, angle, 0);
}
if (stickR.x == 0)
{
LT = false; RT = false;
}
}
}
使い方
左スティックで移動
右スティックで回転
右スティック押し込みでリセンタリング(デバッグ時のみ)
余談
Oculus+UnityでVRやりたい場合はアセットストアから「Oculus Integration」をインポートすれば大体のことはできる。
が、そんなに機能要らない。。もっと簡単にスクリプトちょっとくっつけるだけでワールドを歩き回りたい!
と思っていたらUnityがVRテンプレートを提供してくれてたので使わせてもらいました。入力関連はどんどんアップデートしてくれているので、
今後さらにシンプルに使えるようになれたらいいね。Unityさんマジ最高です。
参考
[Unityマニュアル:Unity の XR 入力] (https://docs.unity3d.com/ja/current/Manual/xr_input.html)