MRが楽しい

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

MRTKのObjectManipulatorで箱を開く動作を行う その2(反対方向への回転を考慮する)

本日は MRTK の小ネタ枠です。
MRTKのObjectManipulatorで箱を開く動作を試してみたので記事にします。
f:id:bluebirdofoz:20211213232657j:plain

前回記事

以下の記事の続きです。
こちらで紹介したスクリプトにあった問題点を改修しました。
bluebirdofoz.hatenablog.com
bluebirdofoz.hatenablog.com

前回記事での問題点と改修

前回記事のスクリプトではX軸の回転のみを参照していたため、正負の判定が正常に動作しませんでした。
このため、ハンドルを反対側に回しても反対側にはオブジェクトが回転しない問題が発生します。
f:id:bluebirdofoz:20211213232719j:plain

スクリプトを以下の通り修正しました。
回転の正負を判定して回転量を調整する実装を追加しています。
・LockAxisLookAtTracker.cs

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

public class LockAxisLookAtTracker : MonoBehaviour
{
    // 固定軸の指定
    // (LookAtはZ軸の正方向(forward)へ追従するためZ軸固定はない)
    private enum TrackingAxis
    {
        XAxis,
        YAxis,
    }

    [Tooltip("追跡の有効無効")]
    public bool IsLookAt = true;

    [Tooltip("LookAt対象のランスフォーム")]
    public Transform LookAtTransform;

    [SerializeField, Tooltip("固定軸の指定")]
    private TrackingAxis LockTrackingAxis;

    void Update()
    {
        if (IsLookAt)
        {
            Tracking();
        }
    }

    /// <summary>
    /// 軸設定に合わせてLookAt方向を回転追跡する
    /// </summary>
    private void Tracking()
    {
        if (LookAtTransform == null) return;

        // LookAt関数を実行してオブジェクト方向への回転を取得する
        this.transform.LookAt(LookAtTransform);
        float xEulerAngle = this.transform.localEulerAngles.x;
        float yEulerAngle = this.transform.localEulerAngles.y;
        float zEulerAngle = this.transform.localEulerAngles.z;

        // XまたはY軸固定の回転に変換しなおす
        switch (LockTrackingAxis)
        {
            case TrackingAxis.XAxis:
                xEulerAngle = IsPositiveAngle(yEulerAngle) ? xEulerAngle : ReverseAngle(xEulerAngle);
                yEulerAngle = 0.0f;
                zEulerAngle = 0.0f;
                break;
            case TrackingAxis.YAxis:
                xEulerAngle = 0.0f;
                yEulerAngle = IsPositiveAngle(xEulerAngle) ? yEulerAngle : ReverseAngle(yEulerAngle);
                zEulerAngle = 0.0f;
                break;
            default:
                break;
        }

        this.transform.localEulerAngles = new Vector3(xEulerAngle, yEulerAngle, zEulerAngle);
    }

    /// <summary>
    /// 回転の正負(true:正)
    /// </summary>
    private bool IsPositiveAngle(float angle)
    {
        if ((270.0f > angle) && (angle >= 90.0f)) return false;
        return true;
    }

    /// <summary>
    /// 回転の正負反転
    /// </summary>
    private float ReverseAngle(float angle)
    {
        if ((0.0f <= angle) && (angle < 180.0f))
        {
            return (90.0f - angle) + 90.0f;
        }
        return (270.0f - angle) + 270.0f;
    }
}

オブジェクトにスクリプトを設定し、ハンドルオブジェクトへの参照を追加します。
f:id:bluebirdofoz:20211213232731j:plain

動作確認

シーンを再生して動作を確認します。
f:id:bluebirdofoz:20211213232741j:plain

以下の通り、反対方向への回転も対応できるようになりました。
f:id:bluebirdofoz:20211213232751j:plain