MRが楽しい

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

HoloLens2でホロモンアプリを作る その3(HeadLookControllerでカメラの方を見る)

本日はアプリ作成枠です。
HoloLens2でホロモンアプリを作る進捗を書き留めていきます。
f:id:bluebirdofoz:20210104214059j:plain

本記事はHeadLookControllerでカメラの方を見る設定です。

Head Look Controller

キャラクターの頭部ボーンのアニメーションをオーバライドしてカメラの方向を向けるアセットです。
ただし現在はアセットの更新がされておらず、アセットが非公開の状態になっています。
assetstore.unity.com

本記事では過去記事で取得したソースコードを元に設定を行いました。
bluebirdofoz.hatenablog.com

過去ソースコードを利用する場合、Unity 2018、2019 ではスクリプトを正常に動作させるため、一部コードを修正する必要があります。
nekuramakura.com

ソースコードの修正

Assets/HeadLookController/Script 配下の CursorHit.cs のコードを修正します。
f:id:bluebirdofoz:20210104214557j:plain

16行目~20行目のコードをコメントアウトするだけです。

using UnityEngine;
using System.Collections;

public class CursorHit : MonoBehaviour {
	
	public HeadLookController headLook;
	private float offset = 1.5f;
	
	// Update is called once per frame
	void LateUpdate () {
		if (Input.GetKey(KeyCode.UpArrow))
			offset += Time.deltaTime;
		if (Input.GetKey(KeyCode.DownArrow))
			offset -= Time.deltaTime;

		/* Unity 2019 環境では無効化する */
		// Ray cursorRay = Camera.main.ScreenPointToRay(Input.mousePosition);
		// RaycastHit hit;
		// if (Physics.Raycast(cursorRay, out hit)) {
		// 	transform.position = hit.point + offset * Vector3.up;
		// }

		headLook.target = transform.position;
	}
}

HeadLookControllerの設定

HeadLookController はキャラクターの頭部オブジェクトをカメラの方向に追従させます。
適当なオブジェクトに HeadLookController スクリプトをアタッチします。
f:id:bluebirdofoz:20210104214212j:plain

Inspector ビューから回転する部分や回転角度などの設定を行います。
[Segments]の[Size]から[Element]を追加して[Transform]で動く部位を指定できます。
[Override Animation]にチェックを入れることで指定部位のアニメーションを上書きします。
f:id:bluebirdofoz:20210104214221j:plain

今回、他の身体の部分のアニメーションを上書きしたくなかったので、頭部の部分のみをオーバーライドする設定を行いました。

CursorHitの設定

次に追従させたい対象オブジェクトを指定します。
今回はカメラの方向を向けたいので、カメラの子オブジェクトを用意して CursorHit スクリプトをアタッチしました。
f:id:bluebirdofoz:20210104214231j:plain

Inspector ビューの[Head Look]に先ほど HeadLookController を設定したオブジェクトを指定します。
f:id:bluebirdofoz:20210104214241j:plain

これで設定は完了です。

動作確認

シーンを再生して確認します。
ホロモンのアニメーションの首の部分が上書きされて常にカメラの方を向くようになりました。
f:id:bluebirdofoz:20210104214254j:plain

[MaxBendingAngle]の値を切り替えることでスムーズに振り向きの有効無効を切り替えることができます。
f:id:bluebirdofoz:20210104214303j:plain

切り替えスクリプト一例

コンポーネントの bool 値を切り替えることでスムーズに振り向きの有効無効を切り替えるスクリプトを作ってみました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// リアクティブプロパティ利用のため UniRx を使用
using UniRx;

namespace HMProject
{
    [RequireComponent(typeof(HeadLookController))]
    public class HeadLookSwitch : MonoBehaviour
    {
        [SerializeField, Tooltip("HeadLookの有効無効")]
        public BoolReactiveProperty isEnableReactive = new BoolReactiveProperty(true);

        /// <summary>
        /// HeadLookControllerの参照
        /// </summary>
        private HeadLookController headLookController;

        /// <summary>
        /// HeadLookControllerの最大角デフォルト設定
        /// </summary>
        private float[] defaultMaxBendingAngles;

        /// <summary>
        /// HeadLookControllerのアニメーション上書きのデフォルト設定
        /// </summary>
        private bool defaultOverrideAnimation;

        // Start is called before the first frame update
        void Start()
        {
            // 参照の取得
            headLookController = this.GetComponent<HeadLookController>();
            // デフォルトの最大角の取得
            int segmentnum = headLookController.segments.Length;
            if (segmentnum > 0)
            {
                defaultMaxBendingAngles = new float[segmentnum];
                for (int loop = 0; loop < segmentnum; loop++)
                {
                    defaultMaxBendingAngles[loop] = headLookController.segments[loop].maxBendingAngle;
                }
            }
            // デフォルトのアニメーション上書き設定の取得
            defaultOverrideAnimation = headLookController.overrideAnimation;
            // 有効無効切り替え時のリアクティブ処理を設定する
            isEnableReactive.Subscribe(
                onoff => ChangeMaxBendingAngle(onoff),
                () => ChangeMaxBendingAngle(true)
            );
        }

        /// <summary>
        /// 有効無効に合わせてHeadLookControllerの最大角を変更する
        /// </summary>
        /// <param name="onoff"></param>
        void ChangeMaxBendingAngle(bool onoff)
        {
            // 有効無効に合わせてHeadLookControllerの最大角を変更する
            int segmentnum = headLookController.segments.Length;
            if (segmentnum > 0)
            {
                for (int loop = 0; loop < segmentnum; loop++)
                {
                    float setValue = 0;
                    if (onoff)
                    {
                        setValue = defaultMaxBendingAngles[loop];
                    }
                    headLookController.segments[loop].maxBendingAngle = setValue;
                }
            }

            // アニメーションの上書き設定も変更する
            if (onoff)
            {
                headLookController.overrideAnimation = defaultOverrideAnimation;
            }
            else
            {
                headLookController.overrideAnimation = false;
            }
        }
    }
}

f:id:bluebirdofoz:20210104214313j:plain