xin9le.net

Microsoft の製品/技術が大好きな Microsoft MVP な管理人の技術ブログです。

HTC Vive でコナミコマンド実装してみた

先日 Japan VR Summit 2 に向けて制作し、ブース展示した Grani VR Office Tour。その開発の一環でデバッグコマンドを入れていました。要件はこんな感じ。

  • 特殊なコマンド入力したらとある処理が発動
  • 普段の操作ではまず入力できない難易度
  • 覚えやすい

「それってコナミコマンドだよね!」ということで、HTC Vive コントローラーで動くコナミコマンドを実装しました。

f:id:xin9le:20161122164006p:plain

サンプルコード

実装は極めてシンプルで、UniRx を使えばチョチョイのチョイで終わります。以下がその実装例。なんとコレだけ!あとは発動時に実行したい任意の処理を書くだけです。

//--- こんな感じでボタンが定義されていたとして
public enum Buttons
{
    Top,
    Bottom,
    Left,
    Right,
    A,
    B,
}


public class KonamiCommand : MonoBehaviour
{
    [SerializeField]
    private GameObject controller;

    private void Start()
    {
        //--- コナミコマンドのボタン順序定義
        var buttonOrder = new []
        {
            Buttons.Top,
            Buttons.Top,
            Buttons.Bottom,
            Buttons.Bottom,
            Buttons.Left,
            Buttons.Right,
            Buttons.Left,
            Buttons.Right,
            Buttons.B,
            Buttons.A,
        };

        //--- UniRx を使って IObservable<T> 化したコントローラーのイベント
        var events = controller.GetComponent<ReactiveControllerEvents>();
        Observable.Merge
        (
            events.TouchpadTopPressedAsObservable().Select(_ => Buttons.Top),
            events.TouchpadBottomPressedAsObservable().Select(_ => Buttons.Bottom),
            events.TouchpadLeftPressedAsObservable().Select(_ => Buttons.Left),
            events.TouchpadRightPressedAsObservable().Select(_ => Buttons.Right),
            events.GripPressedAsObservable().Select(_ => Buttons.B),
            events.ApplicationMenuPressedAsObservable().Select(_ => Buttons.A)
        )
        .Buffer(buttonOrder.Length, 1)
        .Do(xs =>
        {
            //--- とりあえず確認のために console に表示
            var message = string.Join(", ", xs.Select(x => x.ToString()).ToArray());
            Debug.Log(message);
        })
        .Where(xs => buttonOrder.SequenceEqual(xs))  //--- 順序が一致していたら
        .Subscribe(_ =>
        {
            Debug.Log("コナミコマンド発動!");
            //--- do something
        })
        .AddTo(this);
    }
}

f:id:xin9le:20161122190532p:plain

当然ですが、Oculus Touch や他のデバイスでも同様にできます。Let's try!!