(この記事の使用環境: Unity5.5.0f3 Personal、Windows10、SteamVR Plugin 1.2.0、VRTK3.0.1)


VR用アセット「VRTK」の Example 019_Controller_InteractingWithPointer の解説です。
コントローラーからのポインタービームでオブジェクトを使うデモです。
VRTK_InteractingWithPointer

■公式サイトの解説

VRTK公式サイトでこのExampleの解説文及び解説動画を見ることができます。ただし、動画に関してはVRTK旧バージョンのときに作られたものであり、VRTK3.0(以降)では設定等が異なっている場合があることに留意してください。動きを中心に見てもらえれば良いかと思います。

このExampleの解説動画



■VRTKのセットアップ方法および使用されているスクリプトの解説

適宜、以下の記事を参照願います。

■Exampleの解説

VRTK/Examples 内にある当該番号のシーンを呼び出すことで、デモを動かしてみることができます。

このデモシーンでは、コントローラーのポインタービームによってインタラクタブルオブジェクトを使用する方法を見ることができます。タッチパッドを押すことでビームを作動させ、オブジェクトに狙いを定めることで、そのオブジェクトの使用状態をトグル(On /Off)することができます。

また、このデモシーンでは、インタラクティブオブジェクトで作られたゲームメニューを呼び出すこともできます。アプリケーションメニューボタンを押すと、コントローラに接続されたキューブがメニューオプション付きで表示されます。立方体の他のコントローラを使用してビームを指すと、それに応じてメニューオプションが選択されます。
SnapCrab_NoName_2017-2-4_20-32-39_No-00
SnapCrab_NoName_2017-2-4_21-10-56_No-00

以下、シーンに配置されているオブジェクトについての概要説明です。
  • Whirlygig, Whirlygig (2): 土台が緑色のWhirlygig。VRTK_InteractableObject を継承した Whirlygig スクリプトがアタッチされており、そのインスペクタで Pointer Activates Use Action にチェックされているため、コントローラーのポインタービームを当てることによって使用することができる(=上部のオブジェクトが回転する)。この2つのオブジェクトで異なるのは Whirlygig スクリプトの Hold Button To Use の項目のみである。一方のオブジェクトは Hold Button To Use がチェックされているため、ポインタービームが当たっている間のみ使用状態となる。もう一方のオブジェクトはHold Button To Use がチェックされていないため、使用状態はトグルアクションとなり、ポインタービームが当たると使用状態が開始し、もう一度ビームが当たると停止する。
    SnapCrab_NoName_2017-2-4_21-16-38_No-00

  • Whirlygig (1): 土台が赤色のWhirlygig。こちらにも Whirlygig スクリプトがアタッチされているが、Pointer Activates Use Action はチェックされていないため、コントローラーのポインタービームでは使用できない。(直接コントローラーで触れて、トリガーボタンを押すことで使用可能)
    SnapCrab_NoName_2017-2-4_21-25-44_No-00

  • Left Controller、RightController: [VRTK] ゲームオブジェクトの下に配置されている、左右のコントローラー用のVRTKスクリプトをアタッチするゲームオブジェクト。
    VRTK_ControllerEvents 、VRTK_InteractUse、VRTK_SimplePointer 、Controller_Menu 、その他のスクリプトがアタッチされている。

    ポインタースクリプトにより、コントローラーからポインタービームを発することができるようになっている。
    また、Controller_Menu スクリプトはコントローラーのアプリケーションメニューボタンが押されたイベントを受け取り、インスペクタで指定されたメニューオブジェクト(「MenuCube」)をアクティブにする(アプリケーションメニューボタンが離されるとメニューオブジェクトを非アクティブにする)。
    SnapCrab_NoName_2017-2-4_21-36-11_No-00

    Controller_Menu スクリプトの中身はこんな感じ。解説はコード内のコメント参照。
    namespace VRTK.Examples
    {
        using UnityEngine;
    
        // --- メニューオブジェクト呼び出すスクリプト(コントローラーにアタッチされる)-------------------
        public class Controller_Menu : MonoBehaviour
        {
            public GameObject menuObject;
    
            private GameObject clonedMenuObject;
    
            private bool menuInit = false;
            private bool menuActive = false;
    
            // --- 初期化 (アプリケーションメニューボタンのOn/Offに、DoMenuOn/DoMenuOffメソッドを割り当てる)
            private void Start()
            {
                GetComponent<VRTK_ControllerEvents>().AliasMenuOn += new ControllerInteractionEventHandler(DoMenuOn);
                GetComponent<VRTK_ControllerEvents>().AliasMenuOff += new ControllerInteractionEventHandler(DoMenuOff);
                menuInit = false;
                menuActive = false;
            }
    
            // --- メニューオブジェクトの初期化 -------------------------
            private void InitMenu()
            {
                clonedMenuObject = Instantiate(menuObject, transform.position, Quaternion.identity) as GameObject;
                clonedMenuObject.SetActive(true);
                menuInit = true;
            }
    
            // --- メニューオブジェクトをアクティブにする -----------------
            private void DoMenuOn(object sender, ControllerInteractionEventArgs e)
            {
                if (!menuInit)
                {
                    InitMenu();
                }
                clonedMenuObject.SetActive(true);
                menuActive = true;
            }
    
            // --- メニューオブジェクトを非アクティブにする -----------------
            private void DoMenuOff(object sender, ControllerInteractionEventArgs e)
            {
                clonedMenuObject.SetActive(false);
                menuActive = false;
            }
    
            // --- 更新処理(メニューオブジェクトの位置・回転をコントローラーの位置・回転にあわせる)-----------
            private void Update()
            {
                if (menuActive)
                {
                    clonedMenuObject.transform.rotation = transform.rotation;
                    clonedMenuObject.transform.position = transform.position;
                }
            }
        }
    }
    

  • MenuCube: メニューボタンの並んだCubeオブジェクト。ゲーム開始時は非アクティブになっており、コントローラーのアプリケーションメニューボタンを押すことでアクティブとなり呼び出される。下図のHierarchyビューような階層で構成されている。コントローラーのポインタービームで「Button_SpawnCube」・「Button_SpawnSpere」を使用すると、それらのオブジェクトの位置からCubeまたはSphereが生成される。「Button_MakeX」オブジェクトを使用することで、生成するオブジェクトの色を変更することができる。
    SnapCrab_NoName_2017-2-4_21-58-39_No-00
    MenuCube には以下の3種類のスクリプトがアタッチされている。

  • Menu_Object_Spawner: 「Button_SpawnCube」・「Button_SpawnSpere」オブジェクトにアタッチされているスクリプト。VRTK_InteractableObject を継承・拡張しており、(インスペクタで)生成するオブジェクトの種類を指定できる(Cube または Sphere)。
    SnapCrab_NoName_2017-2-4_22-8-6_No-00

    Menu_Object_Spawner スクリプトの中身。
    namespace VRTK.Examples
    {
        using UnityEngine;
    
        // --- オブジェクトを生成する -------------------------------------------
        public class Menu_Object_Spawner : VRTK_InteractableObject
        {
            public enum PrimitiveTypes
            {
                Cube,           // Cube
                Sphere          // Sphere
            }
    
            public PrimitiveTypes shape;
            private Color selectedColor;
    
            // --- 色をセット ------------------------------
            public void SetSelectedColor(Color color)
            {
                selectedColor = color;
                gameObject.GetComponent<MeshRenderer>().material.color = color;
            }
    
            // --- 使用開始すると、Cube または Sphere を生成する -----------------
            public override void StartUsing(GameObject usingObject)
            {
                base.StartUsing(usingObject);
    
                if (shape == PrimitiveTypes.Cube)
                {
                    CreateShape(PrimitiveType.Cube, selectedColor);
                }
                else if (shape == PrimitiveTypes.Sphere)
                {
                    CreateShape(PrimitiveType.Sphere, selectedColor);
                }
                ResetMenuItems();
            }
    
            // --- オブジェクトを生成する処理の中身 ------------------------------
            private void CreateShape(PrimitiveType shape, Color color)
            {
                GameObject obj = GameObject.CreatePrimitive(shape);
                obj.transform.position = transform.position;
                obj.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
                obj.GetComponent<MeshRenderer>().material.color = color;
                obj.AddComponent<Rigidbody>();
            }
    
            // --- 使用を停止する ------------------------------
            private void ResetMenuItems()
            {
                foreach (Menu_Object_Spawner menuObjectSpawner in FindObjectsOfType<Menu_Object_Spawner>())
                {
                    menuObjectSpawner.StopUsing(null);
                }
            }
        }
    }
    

  • Menu_Color_Changer: 「Button_MakeRed」・「Button_MakeYellow」・「Button_MakeBlue」オブジェクトにアタッチされているスクリプト。VRTK_InteractableObject を継承・拡張しており、(インスペクタで)生成するオブジェクトの色を指定できる。
    SnapCrab_NoName_2017-2-4_22-20-1_No-00

    Menu_Color_Changer スクリプトの中身。
    namespace VRTK.Examples
    {
        using UnityEngine;
    
        // --- カラーチェンジャー(ボタンオブジェクトにセットされる) ----------------------------------------
        public class Menu_Color_Changer : VRTK_InteractableObject
        {
            public Color newMenuColor = Color.black;  // セットする色
    
            // --- 使用すると、セットする色の情報を親オブジェクトの Menu_Container_Object_Colors スクリプトに渡す ------
            public override void StartUsing(GameObject usingObject)
            {
                base.StartUsing(usingObject);
                transform.parent.gameObject.GetComponent<Menu_Container_Object_Colors>().SetSelectedColor(newMenuColor);
                ResetMenuItems();
            }
    
            // --- インスペクタで指定した色にボタンの色をあわせる -----------------
            protected override void OnEnable()
            {
                base.OnEnable();
                gameObject.GetComponent<MeshRenderer>().material.color = newMenuColor;
            }
    
            // --- 使用を止める -----------------
            private void ResetMenuItems()
            {
                foreach (Menu_Color_Changer menuColorChanger in FindObjectsOfType<Menu_Color_Changer>())
                {
                    menuColorChanger.StopUsing(null);
                }
            }
        }
    }
    

  • Menu_Container_Object_Colors: ボタンをまとめる BoxContainer オブジェクトにアタッチされているスクリプト。Menu_Color_Changer スクリプトから受け取った色変更情報をすべての子オブジェクトの Menu_Object_Spawner スクリプトに伝える。
    SnapCrab_NoName_2017-2-4_22-26-39_No-00

    Menu_Container_Object_Colors スクリプトの中身。
    namespace VRTK.Examples
    {
        using UnityEngine;
    
        // --- 生成するオブジェクトの色をセットする ------------------------------------
        public class Menu_Container_Object_Colors : VRTK_InteractableObject
        {
            public void SetSelectedColor(Color color)
            {
                foreach (Menu_Object_Spawner menuObjectSpawner in gameObject.GetComponentsInChildren<Menu_Object_Spawner>())
                {
                    menuObjectSpawner.SetSelectedColor(color);  // すべての子オブジェクトの Menu_Object_Spawner に色をセットする
                }
            }
    
            protected void Start()
            {
                SetSelectedColor(Color.red);
                SaveCurrentState();
            }
        }
    }
    

今回は以上です。