本日は MRTK の小ネタ枠です。
MRTKのObjectManipulatorで箱を開く動作を試してみたので記事にします。
前提条件
以下の記事で作成した蓋オブジェクトを設定した段ボールモデルを利用します。
bluebirdofoz.hatenablog.com
サンプルプロジェクトの作成
MRTK をインポートしたサンプルプロジェクトを作成します。
MRTK のインポートと基本設定
MRTK のインポートと HoloLens 向けプロジェクトの基本設定を行い、サンプルプロジェクトを作成します。
手順の詳細は以下の記事を参照してください。
bluebirdofoz.hatenablog.com
サンプルシーンの作成
MRTKの基本設定を行ったうえで以下の通り段ボールオブジェクトを配置したシーンを準備しました。
Collider でオブジェクトのアタリ判定を設定します。
このとき、段ボールの本体のアタリ判定と箱を開けるためのハンドルのアタリ判定を別々に設定しておきます。
この状態で本体とハンドルそれぞれに ObjectManipulator を設定します。
これで本体とハンドルのオブジェクトを別々に掴んで動かすことができます。
サンプルスクリプト
後は本体の蓋オブジェクトのみ、ハンドルオブジェクトの移動に合わせて回転動作を行います。
以下の LookAt 関数を用いて特定方向の軸回転を行うスクリプトを作成しました。
・HandleLookAtController.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class HandleLookAtController : MonoBehaviour { private enum TrackingAxis { All, XAxis, YAxis, ZAxis, } [SerializeField, Tooltip("追跡の有効無効")] private bool p_isLookAtTracking; [SerializeField, Tooltip("軸の反転フラグ")] private bool p_isReverse; [SerializeField, Tooltip("LookAt対象のハンドルトランスフォーム")] private Transform p_LookAtHandleTransform; [SerializeField, Tooltip("ローカル回転軸の指定")] private TrackingAxis p_LocalTrackingAxis; [SerializeField, Tooltip("ハンドルリセット位置のトランスフォーム")] private Transform p_HandleResetTransform; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { if (p_isLookAtTracking) { Tracking(); } } /// <summary> /// 追跡フラグの切り替え /// </summary> /// <param name="onoff"></param> public void ChangeLookAtTracking(bool onoff) { p_isLookAtTracking = onoff; } /// <summary> /// ハンドルの位置を動きに合わせてリセットする /// </summary> public void ResetHandlePosition() { p_LookAtHandleTransform.transform.position = p_HandleResetTransform.position; p_LookAtHandleTransform.transform.rotation = p_HandleResetTransform.rotation; } /// <summary> /// 角度の手動変更 /// </summary> /// <param name="a_LocalEulerAngle"></param> public void ChangeAngle(Vector3 a_LocalEulerAngle) { this.transform.localEulerAngles = a_LocalEulerAngle; // ハンドル位置をリセット ResetHandlePosition(); } /// <summary> /// 軸設定に合わせてLookAt方向を追跡する /// </summary> private void Tracking() { if (p_LookAtHandleTransform != null) { this.transform.LookAt(p_LookAtHandleTransform); float reverseFact = 1.0f; if (p_isReverse) reverseFact = -1.0f; switch (p_LocalTrackingAxis) { case TrackingAxis.All: this.transform.localEulerAngles = new Vector3( reverseFact * this.transform.localEulerAngles.x, reverseFact * this.transform.localEulerAngles.y, reverseFact * this.transform.localEulerAngles.z ); break; case TrackingAxis.XAxis: this.transform.localEulerAngles = new Vector3( reverseFact * this.transform.localEulerAngles.x, 0.0f, 0.0f ); break; case TrackingAxis.YAxis: this.transform.localEulerAngles = new Vector3( 0.0f, reverseFact * this.transform.localEulerAngles.y, 0.0f ); break; case TrackingAxis.ZAxis: this.transform.localEulerAngles = new Vector3( 0.0f, 0.0f, reverseFact * this.transform.localEulerAngles.z ); break; default: break; } } } }
蓋オブジェクトに本スクリプトを設定します。
p_HandleResetTransform 変数にはハンドルを離した際、ハンドルのアタリ判定を蓋オブジェクトの見た目に合わせるためのリセット位置を指定します。
ObjectManipulator の OnManipulationEnded 関数にスクリプトの ResetHandlePosition 関数を指定しておきます。
これにより、ハンドルを手放すと、ハンドルのアタリ判定の位置がリセット位置に移動します。
動作確認
シーンを再生して動作を確認します。
ハンドル位置を掴んで動かすと、蓋オブジェクトが回転して蓋が開きます。
手を離すと、アタリ判定は蓋オブジェクトの指定位置に戻ります。
2021/12/13追記
本記事のスクリプトでは反対方向の回転が考慮されていなかったので反対方向の回転も考慮した改修スクリプトを以下の記事で作成しています。
bluebirdofoz.hatenablog.com