[Unity] FF4、FF5のダメージ表示アニメーションをUnityで再現する
ハイスコアガールのハルオ世代がほいほい釣れそうなFF4やFF5のダメージ数値が表示される時のアニメーションをUnityで再現してみます。実装方法が間違っているかもしれませんが懐かしむ感じで。
FFダメージ表示アニメーション(FF4~6?)
こんな感じのアニメーションを作ってみます。
2015/1/24 触れるもの作ってみました → [Unity] FF1からFF6までのダメージ表示アニメーションを再現する
Contents
実装方法
Twitterで教えていただいた方法
ちなみにやってる事は数秒毎に1文字ずつずらして文字をインスタンス化(ポップアップはアニメーション)、最後にCanvas Groupで一気に全部透明にしてデストローイする感じ。文字の表示が終わらないと透明化タイミングが使い見づらいと思うので、インスタンス化と透明化はスクリプト
— 椿 (@tsubaki_t1) January 4, 2015
すべて答えが載っています。やったね!(Unity初心者の心の中:Canvas Groupって何だろう?文字表示が終わったという判定はどうやるのだろうか?)
アニメーション作成
まずはTextを作ります。Outlineコンポーネントを付けて装飾。フォントサイズは24。幅高さは30にしました。
WindowメニューからAnimationを選択。Animationウィンドウでアニメーションを作成していきます。Add Curveボタンを押し、DamagePopupAnimation.Animファイルを保存します。
数値がポンっと飛び出す感じにアニメーションを作成します。動きは好きなように作りましょう。
アニメーションのループ設定をOFFにします。
※本当は「何もしない状態」「数値が飛び出すアニメーション」「消えるときのアニメーション」「消えた後の状態」の4つアニメーションをコントロールしたかったのですが、判らなかったのでとりあえずポップアップするアニメーションだけ作りました。
※この部分ですがアニメーションを再生し終えたら、AステートからBステートに遷移させる…、なんてことができると思うのですよ・・・。ほいでAnimator.GetState的なメソッドで状態を取れたりすると思うのですよ・・・。今回ははまりそうだったのでパス。
テキスト用スクリプトの作成
作成したTextで「アニメーション終了イベント」を受け取りる為のスクリプトを作成します。
using UnityEngine; using System.Collections; public class NumberTextScript : MonoBehaviour { public bool IsFinish = false; public void OnAnimationFinish() { this.IsFinish = true; } }
作成したらTextにスクリプトを追加します。
アニメーションイベントの追加
アニメーションが終了したときNumberTextScript.OnAnimationFinish(上で作成したスクリプトのメソッド)が呼ばれるように設定します。Animationウィンドウに行き、最終フレームにイベントを追加します。
イベントには先ほど追加したOnAnimationFinishを指定します。
テスト再生とプレハブ化
再生されたでしょうか。よければ作成したTextをPrefab化して消します。Canvasは使うのでそのままで。
休憩
なれない作業でここまでで1.5時間くらいかかってたりします。慣れている人で2~3分程度じゃないだろうか。
ダメージ表示用GameObjectの作成
各文字のアニメーションを行い、自分自身の破棄までの一連の動作を行うスクリプトを作成します。
using UnityEngine; using UnityEngine.UI; using System.Collections; using System.Collections.Generic; public class PopupDamageGen : MonoBehaviour { /// <summary> /// 出力先キャンバス /// </summary> public GameObject TargetCanvas; /// <summary> /// 表示する文字 /// </summary> public string PopupString; /// <summary> /// ポップアップするテキストオブジェクト /// NumberTextScript付き /// </summary> public GameObject PopupTextObject; /// <summary> /// ポップアップする位置 /// </summary> public Vector3 PopupPosition; /// <summary> /// 1文字の幅 /// </summary> public float PopupTextWidth; /// <summary> /// ポップアップの実行 /// </summary> public void Popup() { StartCoroutine (Execute()); } /// <summary> /// ポップアップ実行 /// </summary> private IEnumerator Execute() { var pos = this.PopupPosition; var texts = new List<NumberTextScript> (); var root = new GameObject (); var canvasGroup = root.AddComponent<CanvasGroup> (); root.transform.SetParent (this.TargetCanvas.transform); foreach (var s in this.PopupString) { var obj = new GameObject (); obj.transform.position = pos; obj.transform.SetParent (root.transform); // 1文字ずつ生成 var valueText = (GameObject)Instantiate (this.PopupTextObject, pos, Quaternion.identity); var textComp = valueText.GetComponent<Text> (); textComp.text = s.ToString (); valueText.transform.SetParent (obj.transform); texts.Add( valueText.GetComponent<NumberTextScript>() ); // 0.03秒待つ(適当) yield return new WaitForSeconds (0.03f); // 次の位置 pos.x += this.PopupTextWidth; } // 適当に待ち while (!texts.TrueForAll( t => t.IsFinish )) { yield return new WaitForSeconds (0.1f); } // フェードアウト for (int n=9; n>=0; n--) { canvasGroup.alpha = n / 10.0f; yield return new WaitForSeconds (0.01f); } // 破棄 Destroy (root); Destroy (gameObject); } }
行っていることは
- 一気に透明化できるようにRootとなるGameObject+Canvas Groupの作成(破棄するのも簡単だしね)
- 一定時間ごとに1文字ずつTextオブジェクトを生成する
- アニメーション終了チェック
- Canvas GroupのAlpha値を変えながらフェードアウト処理
- 自分自身の破棄
です。
コルーチンで処理していますが、Updateメソッド内でTime.deltatimeを使った処理の方が正しいかもしれません。フェードアウトしていく処理もText側のアニメーションで作成したほうがデザイン側とコーディング側が分かれて幸せになれるはずですが・・・。
左クリックでポップアップするテストスクリプトを作成(テスト用)
using UnityEngine; using System.Collections; public class Test_PopupDamage : MonoBehaviour { /// <summary> /// 出力先キャンバス /// </summary> public GameObject TargetCanvas; /// <summary> /// ポップアップするテキストオブジェクト /// NumberTextScript付き /// </summary> public GameObject PopupText; // Use this for initialization void Start () { } // Update is called once per frame void Update () { if (Input.GetMouseButtonDown (0)) { var temp = new GameObject(); PopupDamageGen gen = temp.AddComponent<PopupDamageGen>(); gen.PopupString = ((int)(Random.value * 10000.0f)).ToString(); gen.PopupPosition = Input.mousePosition; gen.PopupTextWidth = 20.0f; gen.TargetCanvas = this.TargetCanvas; gen.PopupTextObject = this.PopupText; gen.Popup (); } } }
作成したらCameraにでも追加しましょう。
実行
クリックするとぽろろんっと表示される!
まとめ
どうにか作ってみましたが「Unityの流儀に反しているかも?」とか、「この方法は一般的なんだろうか?」みたいな疑問がいっぱいです。
参考URL
Animatorの終了判定
http://perillasoft.blog75.fc2.com/blog-entry-48.html
コルーチンについて
http://qiita.com/fujimisakari/items/811e350cbaeb45b6165e
“[Unity] FF4、FF5のダメージ表示アニメーションをUnityで再現する | きききろく” http://t.co/T8nx2HTJL7
http://t.co/VHsJEYXN5f [Unity] FF4、FF5のダメージ表示アニメーションをUnityで再現する | きききろく | 30 users
[Unity] FF4、FF5のダメージ表示アニメーションをUnityで再現する http://t.co/7uUOXTOoWS
[Unity] FF4、FF5のダメージ表示アニメーションをUnityで再現する | きききろく http://t.co/m4i85qUSJJ そういうことだったか
これのパクリです。気が向いたらチュートリアル動画にします。 http://t.co/UQIROYcj5H
[Unity] FF4、FF5のダメージ表示アニメーションをUnityで再現する | きききろく http://t.co/kqiPLGvZfN あら( ゚д゚ )
[Unity] FF4、FF5のダメージ表示アニメーションをUnityで再現する | きききろく(45):http://t.co/2erV1QPOJt
[Unity] FF4、FF5のダメージ表示アニメーションをUnityで再現する | きききろく http://t.co/wrm3AIHpo0
[Unity] FF4、FF5のダメージ表示アニメーションをUnityで再現する http://t.co/VMrbsXILUX — すごく参考になりました
3件のコメント http://t.co/PrLXchdV3v “[Unity] FF4、FF5のダメージ表示アニメーションをUnityで再現する | きききろく” http://t.co/PfoWWLebUm