41
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Oculus Goでレーザーポインターを表示する

Oculus Go でコントローラーからレーザーポインター的なガイドを表示する方法を調べたので備忘録として。

out.gif

参考

Use GearVrController with Selection Ray - Unity

基本的にここに書かれている通りにやればOK。

使用中のコントローラー(左右どちら?)を取得する

Oculus Go では左右どちらの手でコントローラーを使うか設定できるので、アプリ内での表示もこの設定に沿う必要があります。現在コントローラーを左右どちらの手で使っているかはOVRInput.GetActiveController で取得できます。

// 現在アクティブなコントローラーを取得
var controller = OVRInput.GetActiveController();
if (controller == OVRInput.Controller.RTrackedRemote)
{
    // 右手
    return _RightHandAnchor;
}
else if (controller == OVRInput.Controller.LTrackedRemote)
{
    // 左手
    return _LeftHandAnchor;
}

OVRInput.GetActiveController はStart やAwake のタイミングでは取得できなかった(OVRInput.Controller.None が返ってくる)ので、Update 中で取得しています(ちょっとハマった。素直に参考記事のとおりにすればよかった)。

Oculus 公式のOVRInput ドキュメントによると、OVRInput.IsControllerConnected でも判定できる模様。

コントローラー位置の取得する

コントローラー(手)の位置そのものはOVRCameraRig に付いているLeftHandAnchor/RightHandAnchor から取得できます。

コントローラーのモデルを表示したい場合はOculus Integration に付属のPrefav、TrackedRemote をLeftHandAnchor/RightHandAnchor 以下にそれぞれ配置すると、右手左手の設定に応じていい具合に表示を切り替えてれます。

ovrcamerarig.png

あとはこの位置からRay を飛ばしてレーザーを表示すればOK。

コード

LaserPointer.cs
public class LaserPointer : MonoBehaviour 
{
    [SerializeField]
    private Transform _RightHandAnchor;

    [SerializeField]
    private Transform _LeftHandAnchor;

    [SerializeField]
    private Transform _CenterEyeAnchor;

    [SerializeField]
    private float _MaxDistance = 100.0f;

    [SerializeField]
    private LineRenderer _LaserPointerRenderer;

    private Transform Pointer
    {
        get
        {
            // 現在アクティブなコントローラーを取得
            var controller = OVRInput.GetActiveController();
            if (controller == OVRInput.Controller.RTrackedRemote)
            {
                return _RightHandAnchor;
            }
            else if (controller == OVRInput.Controller.LTrackedRemote)
            {
                return _LeftHandAnchor;
            }
            // どちらも取れなければ目の間からビームが出る
            return _CenterEyeAnchor;
        }
    }

    void Update () 
    {
        var pointer = Pointer;
        if (pointer == null || _LaserPointerRenderer == null)
        {
            return;
        }
        // コントローラー位置からRayを飛ばす
        Ray pointerRay = new Ray(pointer.position, pointer.forward);

        // レーザーの起点
        _LaserPointerRenderer.SetPosition(0, pointerRay.origin);

        RaycastHit hitInfo;
        if (Physics.Raycast(pointerRay, out hitInfo, _MaxDistance))
        {
            // Rayがヒットしたらそこまで
            _LaserPointerRenderer.SetPosition(1, hitInfo.point);
        }
        else
        {
            // Rayがヒットしなかったら向いている方向にMaxDistance伸ばす
            _LaserPointerRenderer.SetPosition(1, pointerRay.origin + pointerRay.direction * _MaxDistance);
        }
    }
}

lp.png

まとめ

ポインター操作にGaze を使うゲームは分かりやすいんですが首が疲れるので、せっかくなのでコントローラーを使っていきたいと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
41
Help us understand the problem. What are the problem?