MRが楽しい

MRやVRについて学習したことを書き残す

ユニティちゃんと追いかけっこする

ユニティちゃんシリーズの続きとなります。
前回の記事でゲームパッドを元にユニティちゃんを動かしました。

【HoloLens開発】ユニティちゃんとHoloLensで戯れる - ゲームパッド編 -
 http://bril-tech.blogspot.jp/2016/11/hololens-gamepad.html


しかし、折角ハンズフリーのholosensでキャラクターの操作にパッドやキーボードが必要なのも悲しい話です。
今回はユニティちゃんの自動操作を試してみます。

理屈は簡単。hololensでは自分の座標はメインカメラの座標なので
ユニティちゃんは自動操作がオンになると、メインカメラの座標に向かって歩き続けます。

自動操作のトリガーに音声認識を用いて、完全にハンズフリーで操作できるようにします。
f:id:bluebirdofoz:20170414233345j:plain
「here」とユニティちゃんに声をかけると…
f:id:bluebirdofoz:20170414233358j:plain
こちらに向かって歩いてきてくれました。
カメラの座標に向かって歩き続けるので、自身が動くとユニティちゃんはそこに向かって歩きなおします。
鬼ごっこのような遊びが可能です。

XboxOneController.csのコードを参考に、以下のカメラ座標に向かって歩く関数を作成しました。

    // カメラ方向への移動関数
    void moveToMainCamera(float power)
    {
        // メインカメラ(HoloLensの視線)方向を取得
        Vector3 forward = Camera.main.transform.TransformDirection(Vector3.forward);
        Vector3 right = Camera.main.transform.TransformDirection(Vector3.right);
        //Debug.Log("forward:" + forward + ",right:" + right);

        float h;
        float v;
        Vector3 cPosition = Camera.main.transform.position;
        Vector3 uPosition = transform.position;
        float cameraX = cPosition.x;
        float cameraZ = cPosition.z;
        float unityX = uPosition.x;
        float unityZ = uPosition.z;
        float horizontalPos = ((cameraX - unityX) * (right.x)) + ((cameraZ - unityZ) * (right.z));
        float verticalPos = ((cameraZ - unityZ) * (forward.z)) + ((cameraX - unityX) * (forward.x));
        float horizontalRange = horizontalPos;
        float verticalRange = verticalPos;
        if (horizontalPos < 0) horizontalRange = horizontalRange * -1;
        if (verticalPos < 0) verticalRange = verticalRange * -1;
        float sum = horizontalRange + verticalRange;
        float hPer = Mathf.Floor((horizontalRange * 100.0f) / sum);
        float vPer = Mathf.Floor((verticalRange * 100.0f) / sum);
        h = power * (hPer / 100.0f);
        v = power * (vPer / 100.0f);
        if (horizontalPos < 0) h = h * -1;
        if (verticalPos < 0) v = v * -1;

        // カメラ座標による操作
        float speed = Mathf.Sqrt(v * v + h * h);        // vとhから左スティックの傾き具合を算出
        if (speed > 0.1)
        {
            anim.SetFloat("Speed", speed);

            if (Camera.main != null)
            {
                // メインカメラ(HoloLensの視線)方向を取得
                moveDirection = h * right + v * forward;
                velocity = moveDirection * forwardSpeed;

                Vector3 AnimDir = velocity;
                AnimDir.y = 0;
                if (AnimDir.sqrMagnitude > 0.001)
                {
                    // 前進する方向に旋回
                    Vector3 newDir = Vector3.RotateTowards(transform.forward, AnimDir, 10f * Time.deltaTime, 0f);
                    transform.rotation = Quaternion.LookRotation(newDir);
                }

                // 移動処理
                transform.position += velocity * Time.fixedDeltaTime;
            }
        }
    }

苦戦の程がうかがえます。。
メインカメラの座標、ゲームの絶対座標、ユニティちゃんの認識座標が絡むため、
座標の解釈と変換の式の正解を得るのにかなり時間を要しました。
(位置を移動すると意図しない方向へとあっちいったりこっちいったり…)

間違いなくシェイプアップできますが、記録として残しておきます。