本日はUniTaskの小ネタ枠です。
UniTaskを使って徐々に変化するゲージバーを作成する方法を記事に残します。
前回記事
今回は以下の前回記事で作成したゲージバーのサンプルシーンを利用します。
bluebirdofoz.hatenablog.com
UniTaskの環境構築手順は以下を参照ください。
bluebirdofoz.hatenablog.com
UniTask.Yield
UniTaskが戻り値の関数であればUniTask.Yieldを使ってフレーム待機することができます。
これを使って関数内で簡単にフレーム待機の処理を制御できます。
public async UniTask WaitFrame() { // 現在のフレーム番号を取得する var startFrame = Time.frameCount; // 1フレームだけ待機する await UniTask.Yield(PlayerLoopTiming.Update, new CancellationToken()); // 経過フレームを表示する Debug.Log($"現在の経過フレーム:{Time.frameCount - startFrame}"); }
サンプルスクリプト
前回作成したスクリプトを改修して増加関数を呼び出すとゲージを少しずつ増加させるようにしました。
・SmoothStretchGaugeTest.cs
using System.Threading; using Cysharp.Threading.Tasks; using UnityEngine; public class SmoothStretchGaugeTest : MonoBehaviour { /// <summary> /// 全体のサイズ /// </summary> [SerializeField] private RectTransform _totalRectTransform; /// <summary> /// 青ゲージ /// </summary> [SerializeField] private RectTransform _blueRectTransform; /// <summary> /// 赤ゲージ /// </summary> [SerializeField] private RectTransform _redRectTransform; /// <summary> /// 現在の青ゲージの比率 /// </summary> [SerializeField] private float _currentBlueRatio = 0.0f; /// <summary> /// アニメーションの排他制御 /// </summary> private SemaphoreSlim _semaphoreSlim = new (1,1); void Start() { ChangeGauge(_currentBlueRatio); } [ContextMenu("IncrementGauge")] public void IncrementGauge() { var nextRatio = _currentBlueRatio + 10; if (nextRatio > 100) { nextRatio = 100; } ChangeGaugeAnimationAsync((int)nextRatio).Forget(); } public async UniTask ChangeGaugeAnimationAsync( int changeRatio, float tweenTime = 1.0f) { float animationTime = 0; // アニメーション中は排他制御を行い、アニメーションが終わるまで待機する await _semaphoreSlim.WaitAsync(); var animationStartRatio = _currentBlueRatio; var animationEndRatio = changeRatio; while (animationTime < tweenTime) { // ゲージを徐々に変化させる animationTime += Time.deltaTime; var progressRatio = (int)Mathf.Lerp(animationStartRatio, animationEndRatio, animationTime / tweenTime); ChangeGauge(progressRatio); await UniTask.Yield(); } ChangeGauge(animationEndRatio); _currentBlueRatio = changeRatio; // アニメーションが終わったら排他制御を解除する _semaphoreSlim.Release(); } private void ChangeGauge(float blueRatio) { var totalGaugeWidth = _totalRectTransform.rect.width; var blueGaugeWidth = totalGaugeWidth * blueRatio / 100.0f; var redGaugeWidth = totalGaugeWidth - blueGaugeWidth; _blueRectTransform.offsetMin = new Vector2(0, 0); _blueRectTransform.offsetMax = new Vector2(-1.0f * redGaugeWidth, 0); _redRectTransform.offsetMin = new Vector2(blueGaugeWidth, 0); _redRectTransform.offsetMax = new Vector2(0, 0); } }
シーンを再生してIncrementGauge関数を呼び出します。
フレームに合わせてゲージが増加することでスムーズにゲージが変化します。