第08回 数字の表示とアニメーション
2 / 4 数字の生成と一度の再生
このステップの目的
数字の内容を渡して再生し、表示時間が終わると消える状態を作ります。
数字が受け持つ処理
前のステップのDamageNumberを使います。Assets/UNSLOW/EffectPractice/ScriptsへDamageNumber.csを作り、次の全文に置き換えます。このコンポーネントは、表示内容を受け取るSetupと、再生中の表示を更新するUpdateを持ちます。
elapsed / lifeTimeは、秒で進む時間を開始時0、終了時1へ変換します。AnimationCurve.Evaluate(t)は、その時点に対応するカーブの高さを取り出します。Y方向の移動量はUIの単位、Scaleは元の大きさに掛ける倍率、Alphaは元の透明度に掛ける割合です。
csharp
using TMPro;
using UnityEngine;
[RequireComponent(typeof(TextMeshProUGUI))]
public class DamageNumber : MonoBehaviour
{
[SerializeField, Min(0.01f)] private float lifeTime = 1f;
[SerializeField] private AnimationCurve moveCurve = AnimationCurve.Linear(0f, 0f, 1f, 80f);
[SerializeField] private AnimationCurve scaleCurve = AnimationCurve.Linear(0f, 1f, 1f, 1f);
[SerializeField] private AnimationCurve alphaCurve = new(
new Keyframe(0f, 1f), new Keyframe(0.5f, 1f), new Keyframe(1f, 0f));
private RectTransform rect;
private TMP_Text label;
private Vector2 startPosition;
private Vector3 startScale;
private Color startColor;
private float elapsed;
private bool playing;
private void Awake()
{
rect = GetComponent<RectTransform>();
label = GetComponent<TMP_Text>();
startPosition = rect.anchoredPosition;
startScale = rect.localScale;
}
public void Setup(string message, Color color)
{
label.text = message;
startColor = color;
elapsed = 0f;
playing = true;
Apply(0f);
}
private void Update()
{
if (!playing)
return;
elapsed += Time.deltaTime;
float t = lifeTime <= 0f ? 1f : Mathf.Clamp01(elapsed / lifeTime);
Apply(t);
if (t >= 1f)
Destroy(gameObject);
}
private void Apply(float t)
{
rect.anchoredPosition = startPosition + Vector2.up * moveCurve.Evaluate(t);
rect.localScale = startScale * scaleCurve.Evaluate(t);
Color color = startColor;
color.a *= Mathf.Clamp01(alphaCurve.Evaluate(t));
label.color = color;
}
}Consoleにコンパイルエラーがないことを確認し、DamageNumberへ同名のコンポーネントを追加します。ProjectのPrefabsフォルダーへドラッグしてPrefabを保存し、Scene上の数字を削除します。Prefabは有効な状態で保存してください。以降は、再生時にこのPrefabから数字を生成します。
生成する側の準備
同じScriptsフォルダーへDamageNumberPreview.csを作ります。ゲームのダメージ計算に代わり、授業ではこのスクリプトから固定値を渡します。
csharp
using UnityEngine;
public class DamageNumberPreview : MonoBehaviour
{
[SerializeField] private DamageNumber numberPrefab;
[SerializeField] private RectTransform canvasTransform;
[SerializeField] private int value = 120;
[SerializeField] private bool recovery;
[SerializeField] private Color color = Color.white;
private void Start()
{
DamageNumber number = Instantiate(numberPrefab, canvasTransform);
string message = recovery ? $"+{value}" : value.ToString();
number.Setup(message, color);
}
}- 空のGameObjectを
NumberPreviewとして作り、DamageNumberPreviewを追加します。 - Number PrefabへProjectの
DamageNumber、Canvas TransformへHierarchyのCanvasを割り当てます。 - Valueを
120、Recoveryを無効、Colorを白・Alpha1にします。 - Playすると数字が中央に現れ、1秒で上へ移動して消えます。Hierarchyでも生成された数字が削除されることを確認します。
- Playを終了して、もう一度Playします。同じ開始位置から再生されれば成功です。
表示されないときはConsoleのエラー、二つの参照、Prefabが有効か、Canvasの表示方式を確認します。Sceneに数字が残っていた場合は、Prefabから生成されたものと二重になっていないかも確認してください。
チェックリスト
-
Start → Instantiate → Setupの順で内容が渡ることを説明できる。 - Playし直すと同じ位置から現れ、表示時間後に削除される。