MRが楽しい

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

HoloLens2でホロモンアプリを作る その63(瞳孔の収縮をスクリプトから操作する)

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

瞳孔の収縮をスクリプトから操作するメモです。

瞳孔の収縮を操作する

ホロモンの動向を収縮させるため、以下の記事でホロモンの瞳にボーンを仕込みました。
bluebirdofoz.hatenablog.com

今回はこのボーンのスケールをスクリプトから操作することで、任意のタイミングで瞳孔の収縮を発生させます。
LateUpdate からボーンのトランスフォームを操作することで通常のアニメーションを上書きすることができます。

実装スクリプト

瞳孔の収縮を操作するスクリプトを作成しました。
ContractionAction 関数を実行すると左右の瞳孔ボーンに対して LateUpdate のタイミングで収縮のアニメーションを上書き実行します。
・PupilAnimationController.cs

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

using Cysharp.Threading.Tasks;
using UniRx;
using UniRx.Triggers;

public class PupilAnimationController : MonoBehaviour
{
    [SerializeField, Tooltip("右瞳孔の収縮ボーン")]
    private Transform p_RightEyeShrinkage;

    [SerializeField, Tooltip("左瞳孔の収縮ボーン")]
    private Transform p_LeftEyeShrinkage;

    [SerializeField, Tooltip("収縮の最小スケール")]
    private Vector3 p_SpanMinScale;

    [SerializeField, Tooltip("瞳孔アニメーション実行中フラグ")]
    private bool p_EyeAnimationFlg = false;

    // 経過時刻
    private float timeElapsed;

    /// <summary>
    /// 一時アクションの実行のトリガー
    /// </summary>
    IDisposable p_TempActionTrigger;

    /// <summary>
    /// 瞳孔の収縮アクションを実行する
    /// </summary>
    /// <returns></returns>
    [ContextMenu("ExecuteContractionAction")]
    public bool ContractionAction()
    {
        if (p_EyeAnimationFlg) return false;
        p_EyeAnimationFlg = true;

        // 各ステップのアニメーション時間
        float startTimeSpan = 1.0f;
        float keepTimeSpan = 1.0f;
        float endTimeSpan = 3.0f;

        timeElapsed = 0.0f;

        // トリガーを設定済みの場合は一旦破棄する
        p_TempActionTrigger?.Dispose();

        // アニメーション完了後キャンセルのトリガーを実行する
        p_TempActionTrigger = this.LateUpdateAsObservable()
            .Subscribe(_ =>
            {
                timeElapsed += Time.deltaTime;

                float lerpFactor = 0.0f;
                if (timeElapsed < startTimeSpan)
                {
                    // 徐々に瞳を収縮させる
                    lerpFactor = (timeElapsed % startTimeSpan);

                    p_RightEyeShrinkage.localScale = Vector3.Lerp(Vector3.one, p_SpanMinScale, lerpFactor);
                    p_LeftEyeShrinkage.localScale = Vector3.Lerp(Vector3.one, p_SpanMinScale, lerpFactor);
                }
                else if(timeElapsed < startTimeSpan + keepTimeSpan)
                {
                    // 状態をキープする
                    lerpFactor = 1.0f;

                    p_RightEyeShrinkage.localScale = Vector3.Lerp(Vector3.one, p_SpanMinScale, lerpFactor);
                    p_LeftEyeShrinkage.localScale = Vector3.Lerp(Vector3.one, p_SpanMinScale, lerpFactor);
                }
                else if(timeElapsed < startTimeSpan + keepTimeSpan + endTimeSpan)
                {
                    float checkTimeElapsed = timeElapsed - (startTimeSpan + keepTimeSpan);

                    // 徐々に瞳の大きさを元に戻す
                    lerpFactor = 1.0f - (checkTimeElapsed % endTimeSpan);

                    p_RightEyeShrinkage.localScale = Vector3.Lerp(Vector3.one, p_SpanMinScale, lerpFactor);
                    p_LeftEyeShrinkage.localScale = Vector3.Lerp(Vector3.one, p_SpanMinScale, lerpFactor);
                }
                else
                {
                    // アニメーションの終了
                    p_EyeAnimationFlg = false;
                    p_TempActionTrigger.Dispose();
                }
            })
            .AddTo(this);

        return true;
    }
}

f:id:bluebirdofoz:20211015224014j:plain

スクリプトをオブジェクトに設定し、左右の動向ボーンへの参照を設定します。
f:id:bluebirdofoz:20211015224023j:plain

動作確認

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

コンテキストメニューから関数を実行してみます。
f:id:bluebirdofoz:20211015224040j:plain

以下の通り、スクリプトから瞳孔の収縮アニメーションを上書き再生することができました。
f:id:bluebirdofoz:20211015224048j:plain