第4回では、UnityのInput Systemを使ってABXYのボタン入力を取得する方法と、VRコンテンツでのモーションコントロールとボタンの使い分け方を解説します。
VRにおけるボタン操作とは
はじめに、この記事におけるモーションコントロールとボタン操作の違いを説明します。
モーションコントロールは、VRデバイスのコントローラ
VRデバイスが一般的なPCやスマホと比べて特徴的なのはモーションコントロールによっても操作できる点です。ただ、VRだからといってすべての操作をモーションコントロールで完結させる必要はなく、モーションコントロールに合わないことはボタン入力で済ませることも重要です。なお、モーションコントロールはWiiやNintendo Switchをはじめとする家庭用ゲーム機にも実装されていますが、VRは
ボタン操作の3つの型
今回の記事ではUnityでTouchコントローラーのボタンを使う方法について解説します。Unityのボタン入力のしくみそのものは、VRに限らず一般的なゲームパッドやキーボード・
ボタン操作の情報はプログラム上ではほとんどの場合
“bool”
「ボタンを押した瞬間と離した瞬間」
“float”
「ボタンをどれくらい押しているか?」
“Vector2”
「アナログスティック
Touchコントローラーのボタン一覧
それでは、Touchコントローラーのボタンを見てみましょう
Touchコントローラーは一般的なゲームパッドを左右に分割したようなボタン構成になっています。ゲーム慣れしている人であれば
型 | 該当するボタン |
---|---|
bool | Aボタン、Bボタン、右スティック押し込み、ホームボタン |
float | 右トリガーボタン、右グリップボタン |
Vector2 | 右スティック |
型 | 該当するボタン |
---|---|
bool | Xボタン、Yボタン、左スティック押し込み、メニューボタン |
float | 左トリガーボタン、左グリップボタン |
Vector2 | 左スティック |
Touchコントローラーはさらに、他のゲームパッドとは異なり
しかし、これらはたとえば
UnityでTouchコントローラーのボタン入力を取る
New Controls.inputactionsを作成する
それでは、いよいよTouchコントローラーのボタン入力をUnityで取得してみましょう。今回はボタン入力の管理機能New Controls.
」
Input ActionにTouchコントローラーのボタンマップを登録する
新規作成したNew Controls.
をダブルクリックすると出るウィンドウから、Action Mapsという、ボタン入力の割り当ての設定を作成できます。この割り当て設定を、一般的にはマップと呼びます。マップは、
ウィンドウのAction Mapsタブの右にある+ボタンを押すと、新規マップが作成されます。名前は
アクションを作成するとAction Propertiesが表示されます。まず、Action欄にあるAction Typeを設定します。ABXYはいずれもboolのボタンですが、その場合はAction TypeをButtonにしましょう。アナログスティックやアナログトリガーの場合は、Valueに変更します。
次に、作成したActionsの右にあるプラスマークをクリック、もしくは右クリックの
ボタンの一般名称 | Pathでの名称 |
---|---|
Aボタン | <XRController>{RightHand}/primaryButton |
Bボタン | <XRController>{RightHand}/secondaryButton |
Xボタン | <XRController>{LeftHand}/primaryButton |
Yボタン | <XRController>{LeftHand}/secondaryButton |
なお、リスト一覧から探すだけでなく、リストの右側にあるTボタンをクリックすることでボタン配置の文字列を直接テキストで入力することもできます。
Input Actionのボタンのマネージャーを作成する
つぎに、Input Actionで取得したTouchコントローラーのボタンのマネージャーを作成しましょう。Unityのシーンでボタン入力の結果を出すために押しているとき/isPressed()
」押した瞬間/WasPressedThisFrame()
」離した瞬間/WasReleasedThisFrame()
」
using UnityEngine;
using UnityEngine.InputSystem;
public class InputManagerLR : MonoBehaviour
{
static InputManagerLR m_instance;
// あとでInspectorのActionAsset欄にInput Actionを代入する
[SerializeField]
InputActionAsset m_actionAsset;
InputActionMap m_ActionMap;
InputAction m_PrimaryButtonR;
InputAction m_PrimaryButtonL;
InputAction m_SecondaryButtonR;
InputAction m_SecondaryButtonL;
private void Awake()
{
m_instance = this;
// InputActionマネージャーをシーンから破棄しないようにする
GameObject.DontDestroyOnLoad(gameObject);
// Action Mapsの名前を入れる
m_ActionMap = m_actionAsset.FindActionMap("Test");
// Actionsの名前をすべて入れる
m_PrimaryButtonR = m_ActionMap.FindAction("XR_PrimaryButtonR", throwIfNotFound: true);
m_PrimaryButtonL = m_ActionMap.FindAction("XR_PrimaryButtonL", throwIfNotFound: true);
m_SecondaryButtonR = m_ActionMap.FindAction("XR_SecondaryButtonR", throwIfNotFound: true);
m_SecondaryButtonL = m_ActionMap.FindAction("XR_SecondaryButtonL", throwIfNotFound: true);
}
private void OnEnable()
{
m_ActionMap?.Enable();
}
private void OnDisable()
{
m_ActionMap?.Disable();
}
public static bool PrimaryButtonR()
{
return m_instance.m_PrimaryButtonR.IsPressed();
}
public static bool PrimaryButtonR_OnPress()
{
return m_instance.m_PrimaryButtonR.WasPressedThisFrame();
}
public static bool PrimaryButtonR_OnRelease()
{
return m_instance.m_PrimaryButtonR.WasReleasedThisFrame();
}
// 以下PrimaryButtonL、SecondaryButtonR、SecondaryButtonLでも同様に記載
以上のコードを作成したら、シーンに新規作成した空のゲームオブジェクトにスクリプト
マネージャーで管理しているボタン入力の状態を別のスクリプトで呼び出す
さきほどマネージャーを作成したため、別のスクリプトからボタン入力の情報を呼び出せるようになりました。ボタン入力の判定はUpdate()
で毎フレーム行い、検知した場合にのみ指定の関数を実行するようにします。これにゲームオブジェクトとそのスクリプト・
using Unity.VRTemplate;
using UnityEngine;
public class InputTextLR : MonoBehaviour
{
// ボタン入力をさらに他の関数から呼び出したい場合は、
// 適宜ゲームオブジェクトの変数を用意してそれらの関数を呼び出す
// このプロジェクトの場合はスクリプト"GrabProjectile"を有する
// ゲームオブジェクトのみ代入可能となっている
public GravProjectile m_gravProjectileR;
public GravProjectile m_gravProjectileL;
// Update is called once per frame
// 毎フレームごとにボタン入力の情報を取得する
void Update()
{
if (InputManagerLR.PrimaryButtonR())
{
OnPrimaryButtonR();
}
if (InputManagerLR.PrimaryButtonR_OnPress())
{
OnPressPrimaryButtonR();
}
// 以下PrimaryButtonL、SecondaryButtonR、SecondaryButtonLでも同様に記載
// 以下では、ボタン入力の情報が取得できたときに呼び出す関数
void OnPrimaryButtonR()
{
// ここをコメントアウトしているのは、
// 毎フレームごとにログテキストが表示されると邪魔になるため
// UnityEngine.Debug.Log("PrimaryButtonRを押している");
}
void OnPressPrimaryButtonR()
{
UnityEngine.Debug.Log("PrimaryButtonRを押した瞬間");
// gameObjectの変数に入れたゲームオブジェクトのうち
// スクリプトGravProjectileに入っているDropObjRight関数を呼び出している
m_gravProjectileR.DropObjRight();
m_gravProjectileL.DropObjRight();
}
void OnReleasePrimaryButtonR()
{
UnityEngine.Debug.Log("PrimaryButtonRを離した瞬間");
}
// 以下PrimaryButtonL、SecondaryButtonR、SecondaryButtonLでも同様に記載
コードを作成したら、シーンに新規作成した空のゲームオブジェクトにスクリプト
上記のコードは別ゲームオブジェクトに紐づけるサンプルとして、GravProjectile
レギュレーションが決まっているボタンはそれに合わせよう
押さえておくべきレギュレーションや慣習
さきほどUnityでMeta QuestのコントローラのABXYボタンを取得する方法を解説しました。残るはスティックとトリガーボタン、グリップボタンですが、実のところこれらについてはUnity側のスクリプトできっちり管理されていたり、役割が決まっていることがほとんどです
これまでの連載でもその規定されている役割に沿って、連載第2回ではスティック入力でプレイヤーが移動する方法について、連載第3回ではトリガーボタン・
なお、Unityではなく、Metaのレギュレーションによってもボタンの使い方が決められていることがあります。たとえばVRC.
ほか、Metaのレギュレーションに記載はありませんが、VRゲームにおいては一般的に
EXTRA: VRで有効なボタンの使い方
以下の内容は技術的な解説というよりは補足話となりますが、言及されることは少ないものの重要な話として、VRボタンの課題について少し解説します。
課題1 ボタン配置をユーザーが確認しづらい、覚えづらい
VRのコンテンツにおいて、
これの対応としては、一つ目に
二つ目に、視覚的な対応として
課題2 float、Vector2の情報を活用する機会が限定的
つぎに、VR固有の課題として、VR上で精密・
その他、たとえばAボタンを連打することがテーマのVRゲームを作ろうとしても
さいごに
本連載は第4回をもって最終回を迎えました。そこで、これまでの記事からポイントを振り返ります。
あらためて、VRで肝心なのは、ヘッドセットのディスプレイによる視覚情報と、モーションコントロールによる身体の動きがセットになることで肉体的な実感を伴う行動ができることです。視覚と身体の動きの両方の特性を考慮することで
つぎに、VRがユーザーの肉体を入力端末として使う以上はVR酔いに考慮しなければいけません。これはカメラ
さいごに、開発者である前にユーザーの心を忘れないようにしてください。VRコンテンツを作るのにVRゲームのマニアである必要はありませんが、いちユーザーとしての目線が欠けたまま開発しつづけるとユーザーに響かなかったり理解されなかったりする事態に陥るリスクが高まります。定期的に新しいVRコンテンツに触れたり、家族や友人など適切な方にテストプレイをしてもらい意見を求めたりして視点をリセットしてください。
VRは発展途上ではありますが、Meta Questだけでなく今後さまざまな企業やプラットフォームが立ち上がってさらなる発展を遂げたり、規格競争が生じることでしょう。この先の見えない段階で未知の領域へと踏み込み、新たな発見が連なるのは何事にも代えがたい喜びなのです。