アクティブ化する毎に飛び出すようにScaleを変更するUIモーションをスクリプトのみで再現。
持続時間とディレイ、最小/最大Scaleはインスペクターから設定出来るようにした。
*親Canvasのenabledの切り替えを感知する機能は無いです。
1画面で複数使う場合は、空のオブジェクトにまとめて放り込んでソレをアクティブ化してください。
Animation Curveを使おうとしたが、プリセットの曲線に良い物が無かった為、Mathf.Sinを使用。
サンプル動画
ディレイ無し、ディレイ1.0秒、ディレイ2.0秒を設定したImageを同時にアクティブ化した例。
使い方
基本
- 新規スクリプト「PopoutUI」を作成して、コードを全文貼り付け。
- 対象のUIへアタッチ。
- インスペクターから設定を調整(デフォルト値でもOK)。
複数のUIへ使う場合
2つ目からは、アタッチしたスクリプトを右クリックしてコピペすると早い。
- 【コピー】
- ヒエラルキー -> コピペ元のUIを選択。
- インスペクター -> PopoutUIの上で右クリック -> Copy Component
- 【貼り付け】
- ヒエラルキー -> コピペ先のUIを選択。
- インスペクター -> 右クリック -> Paste Component As New
【コード】PopoutUI
using System.Collections;
using UnityEngine;
public class PopoutUI : MonoBehaviour
{
//Transformをキャッシュしておく。
Transform tf;
//【任意の値】モーションの長さ。
[Header("モーションの長さ(持続時間)")]
[SerializeField]
float duration = 0.8f;
//【任意の値】アクティブ化されてからモーション開始するまでの遅延。
[Header("モーション開始までのディレイ")]
[SerializeField]
[Range(0, 10.0f)]
float delay = 0;
//【任意の値】最小の大きさ。
[Header("最小Scale(モーション開始時のサイズ)")]
[SerializeField]
Vector3 scaleMin = new Vector3(0, 0, 0);
//【任意の値】最大の大きさ。UIのデフォルトScale * 1.3ぐらいの大きさにすると収まりが良くなる。
[Header("最大Scale(デフォルトScale * 1.3程度の値を推奨)")]
[SerializeField]
Vector3 scaleMax = new Vector3(1.3f, 1.3f, 1.3f);
//デフォルトScaleを記憶。
Vector3 defaultScale;
//コルーチン管理用。
Coroutine popout;
//Sinの曲線を良き所まで使用。
static readonly float Modifier = Mathf.PI * 0.725f;
//経過時間。
float elapsedTime;
//WaitForSecondsでも毎フレームnewすると良くないらしいので、キャッシュしておく。
WaitForSeconds delayWait;
//ポーズ中(TimeScale = 0の時)に使用する場合は、WaitForSecondsRealtimeを使う。
// WaitForSecondsRealtime delayWait;
void Awake()
{
tf = transform;
defaultScale = tf.localScale;
if (delay != 0) {
delayWait = new WaitForSeconds(delay);
//ポーズ中に使用する場合は、WaitForSecondsRealtimeを使う。
// delayWait = new WaitForSecondsRealtime(delay);
}
}
//アクティブ化される度に実行。
void OnEnable()
{
//多重起動防止。
if (popout != null) {
StopCoroutine(popout);
}
popout = StartCoroutine(Popout());
}
IEnumerator Popout()
{
elapsedTime = 0;
if (delay != 0) {
tf.localScale = scaleMin;
yield return delayWait;
}
while (true) {
elapsedTime += Time.deltaTime;
//ポーズ中に使用する場合は、deltaTimeでなくunscaledDeltaTimeを使う。
// elapsedTime += Time.unscaledDeltaTime;
tf.localScale = Vector3.Lerp(scaleMin, scaleMax, Mathf.Sin(elapsedTime / duration * Modifier));
if (duration <= elapsedTime) {
//通常のスケールに戻しておく。
tf.localScale = defaultScale;
popout = null;
yield break;
}
yield return null;
}
}
}