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


VR用アセット「VRTK」の Example 015_Controller_TouchpadAxisControl の解説です。
ラジコンカーを操作するデモです。
SnapCrab_NoName_2017-2-6_16-47-31_No-00

■公式サイトの解説

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

このExampleの解説動画



■VRTKのセットアップ方法および使用されているスクリプトの解説
適宜、以下の記事を参照願います。

■Exampleの解説

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

このデモシーンにはラジコンカーが配置されており、コントローラーで操作することができます。指をタッチパッドの上下方向に動かすと、ラジコンカーは前進/後退します。指をタッチパッド上で左右方向に動かすと、ラジコンカーは向きを変えます。トリガーボタンを引くとジャンプします。これにはトリガー軸を使用しており、トリガーをより深く押し下げるほど、ラジコンカーは高くジャンプします。
SnapCrab_NoName_2017-2-6_16-47-31_No-00

以下、シーンに配置されているオブジェクトについての概要説明です。
  • Arena: シーン上に配置されているオブジェクト群。壁やジャンプ台のように配置されている。
  • Car: ラジコンカー。複数のオブジェクトで構成されている。トップのオブジェクトに RC_Car スクリプトがアタッチされており、ラジコンカーの動き方が記述されている。また、地面に接するようにボックスコライダー(isTrigger)が敷かれており、これにより接地しているか否かを判定し、多段ジャンプしないよう制御している。
    SnapCrab_NoName_2017-2-6_20-30-51_No-00

    RC_Car スクリプトの中身。
    namespace VRTK.Examples
    {
        using UnityEngine;
    
        // --- ラジコンカー -----------------------------------------------
        public class RC_Car : MonoBehaviour
        {
            public float maxAcceleration = 3f;      // 最大加速度
            public float jumpPower = 10f;           // ジャンプ力
    
            private float acceleration = 0.05f;     // 加速度
            private float movementSpeed = 0f;       // 移動速度
            private float rotationSpeed = 180f;     // 転回速度
            private bool isJumping = false;         // ジャンプしているか否か
            private Vector2 touchAxis;
            private float triggerAxis;
            private Rigidbody rb;
            private Vector3 defaultPosition;        // デフォルトの位置
            private Quaternion defaultRotation;     // デフォルトの回転
    
            public void SetTouchAxis(Vector2 data)
            {
                touchAxis = data;
            }
    
            public void SetTriggerAxis(float data)
            {
                triggerAxis = data;
            }
    
            // --- 位置・回転のリセット(ラジコンカーが操作不能になった時などに、初期位置に戻す) ---------
            public void ResetCar()
            {
                transform.position = defaultPosition;
                transform.rotation = defaultRotation;
            }
    
            // --- 初期化 -----------------------------------------------
            private void Awake()
            {
                rb = GetComponent<Rigidbody>();
                defaultPosition = transform.position;
                defaultRotation = transform.rotation;
            }
    
            // --- 更新処理 ----------------------------------------------
            private void FixedUpdate()
            {
                if (isJumping)      // ジャンプしているなら
                {
                    touchAxis.x = 0f;   // 左右の入力を却下
                }
                CalculateSpeed();   // 速度計算
                Move();             // 前進・後退
                Turn();             // 左右の転回
                Jump();             // ジャンプ
            }
    
            // --- 速度計算 -------------------------------------------------
            private void CalculateSpeed()
            {
                if (touchAxis.y != 0f)      // タッチパッド(のY軸方向)に触れられていた場合、その座標に応じて速度計算する
                {
                    movementSpeed += (acceleration * touchAxis.y);
                    movementSpeed = Mathf.Clamp(movementSpeed, -maxAcceleration, maxAcceleration);
                }
                else                        // そうでなければ減速処理する
                {
                    Decelerate();
                }
            }
    
            // --- 減速処理 -------------------------------------------------
            private void Decelerate()
            {
                if (movementSpeed > 0)
                {
                    movementSpeed -= Mathf.Lerp(acceleration, maxAcceleration, 0f);
                }
                else if (movementSpeed < 0)
                {
                    movementSpeed += Mathf.Lerp(acceleration, -maxAcceleration, 0f);
                }
                else
                {
                    movementSpeed = 0;
                }
            }
    
            // --- 前進・後退 -----------------------------------
            private void Move()
            {
                Vector3 movement = transform.forward * movementSpeed * Time.deltaTime;
                rb.MovePosition(rb.position + movement);
            }
    
            // --- 左右の転回 -----------------------------------
            private void Turn()
            {
                float turn = touchAxis.x * rotationSpeed * Time.deltaTime;
                Quaternion turnRotation = Quaternion.Euler(0f, turn, 0f);
                rb.MoveRotation(rb.rotation * turnRotation);
            }
    
            // --- ジャンプ -----------------------------------
            private void Jump()
            {
                if (!isJumping && triggerAxis > 0)
                {
                    float jumpHeight = (triggerAxis * jumpPower);
                    rb.AddRelativeForce(Vector3.up * jumpHeight);
                    triggerAxis = 0f;
                }
            }
    
            // --- 地面に接していれば、ジャンプしていない -----------------
            private void OnTriggerStay(Collider collider)
            {
                isJumping = false;
            }
    
            // --- 地面から離れたら、ジャンプしている -----------------
            private void OnTriggerExit(Collider collider)
            {
                isJumping = true;
            }
        }
    }
    

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

    RC_Car_Controller スクリプトに、コントローラーの操作に応じてラジコンカーを動かす処理が記述されている。
    SnapCrab_NoName_2017-2-6_20-52-12_No-00

    RC_Car_Controller スクリプトの中身。
    namespace VRTK.Examples
    {
        using UnityEngine;
    
        // --- ラジコンカーのコントローラー操作 -------------------------
        public class RC_Car_Controller : MonoBehaviour
        {
            public GameObject rcCar;
            private RC_Car rcCarScript;
    
            // --- 初期化(コントローラーの各ボタンの処理を VRTK_ControllerEvents に紐づける) ------------------------
            private void Start()
            {
                rcCarScript = rcCar.GetComponent<RC_Car>();
                GetComponent<VRTK_ControllerEvents>().TriggerAxisChanged += new ControllerInteractionEventHandler(DoTriggerAxisChanged);
                GetComponent<VRTK_ControllerEvents>().TouchpadAxisChanged += new ControllerInteractionEventHandler(DoTouchpadAxisChanged);
    
                GetComponent<VRTK_ControllerEvents>().TriggerReleased += new ControllerInteractionEventHandler(DoTriggerReleased);
                GetComponent<VRTK_ControllerEvents>().TouchpadTouchEnd += new ControllerInteractionEventHandler(DoTouchpadTouchEnd);
    
                GetComponent<VRTK_ControllerEvents>().ButtonOnePressed += new ControllerInteractionEventHandler(DoCarReset);
            }
    
            // --- タッチパッドの座標変更 -----------------
            private void DoTouchpadAxisChanged(object sender, ControllerInteractionEventArgs e)
            {
                rcCarScript.SetTouchAxis(e.touchpadAxis);
            }
    
            // --- トリガー軸の変更(トリガーボタンを押し込む深さ) -----------------
            private void DoTriggerAxisChanged(object sender, ControllerInteractionEventArgs e)
            {
                rcCarScript.SetTriggerAxis(e.buttonPressure);
            }
    
            // --- タッチパッドを離した -------------
            private void DoTouchpadTouchEnd(object sender, ControllerInteractionEventArgs e)
            {
                rcCarScript.SetTouchAxis(Vector2.zero);
            }
    
            // --- トリガーボタンを離した -------------
            private void DoTriggerReleased(object sender, ControllerInteractionEventArgs e)
            {
                rcCarScript.SetTriggerAxis(0f);
            }
    
            // --- アプリケーションメニューボタンを押した(ラジコンカーの位置リセット)---------
            private void DoCarReset(object sender, ControllerInteractionEventArgs e)
            {
                rcCarScript.ResetCar();
            }
        }
    }
    

今回は以上です。