Skip to content

Instantly share code, notes, and snippets.

@anzfactory
Last active May 31, 2016 16:51
Show Gist options
  • Save anzfactory/74b9b902638951c0258d7283c7f34423 to your computer and use it in GitHub Desktop.
Save anzfactory/74b9b902638951c0258d7283c7f34423 to your computer and use it in GitHub Desktop.
数字テキストを良い感じにアニメーションさせて表示するやつ http://anz-note.tumblr.com/post/145157295266
/*********************************
* 数字テキストを良い感じにアニメーションして
* 表示するやーつ
*********************************/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class Number : MonoBehaviour
{
/// <summary>
/// 表示する値
/// </summary>
[SerializeField] private int value;
/// <summary>
/// 文字色
/// </summary>
[SerializeField] private Color textColor = Color.white;
/// <summary>
/// フォント
/// </summary>
[SerializeField] private Font textFont;
/// <summary>
/// 表示したときのアニメーションタイプ
/// </summary>
[SerializeField] private DisplayAnimation currentAnimation = DisplayAnimation.None;
/// <summary>
/// 開始時にアニメーションするかどうか
/// 開始時は表示するだけで、更新した時だけアニメーションしたい場合はfalse
/// </summary>
[SerializeField] private bool animateWhenStart = false;
public enum DisplayAnimation {
None, Wave, Scale, Rotate
}
private RectTransform rectTransform;
private List<NumberText> list;
private GameObject template;
private List<Vector2> sizeList;
private float startX = 0;
public int Value {
get { return this.value; }
set {
this.value = value;
UpdateValue(this.currentAnimation);
}
}
public DisplayAnimation CurrentAnimation {
get { return this.currentAnimation; }
set { this.currentAnimation = value; }
}
private void Awake()
{
this.rectTransform = this.gameObject.GetComponent<RectTransform>();
this.list = new List<NumberText>();
this.sizeList = new List<Vector2>();
}
private void Start()
{
this.template = CreateTemplateText();
PreLoadSize();
UpdateValue(this.animateWhenStart ? this.currentAnimation : DisplayAnimation.None);
}
/// <summary>
/// 値を更新して表示(アニメーション指定があれば実行する)
/// </summary>
private void UpdateValue(DisplayAnimation animation)
{
var str = this.value.ToString();
this.startX = this.rectTransform.rect.width * -0.5f;
for (int i = 0; i < str.Length; i++) {
var s = str[i];
NumberText text;
if (this.list.Count > i) {
// 既存Text再利用
text = this.list[i];
} else {
// Text作って表示して保持
text = CreateText();
this.list.Add(text);
}
text.text = s.ToString();
AdjustRect(text.gameObject, int.Parse(s.ToString()), i);
switch (animation) {
case DisplayAnimation.Wave:
text.AnimateWave(0.1f * i);
break;
case DisplayAnimation.Scale:
text.AnimateScale(0.1f * i);
break;
case DisplayAnimation.Rotate:
text.AnimateRotate(0.2f * i);
break;
case DisplayAnimation.None:
default:
// なにもなし
break;
}
}
// 余分なやつを消す
for (int i = str.Length; i < this.list.Count; i++) {
this.list[i].gameObject.SetActive(false);
}
}
/// <summary>
/// 新たにText入れ物をつくる
/// </summary>
/// <returns>The text.</returns>
private NumberText CreateText()
{
var gameObject = Instantiate(this.template) as GameObject;
gameObject.SetActive(true);
gameObject.transform.SetParent(this.gameObject.transform);
return gameObject.GetComponent<NumberText>();
}
/// <summary>
/// テンプレートテキストをつくる
/// </summary>
/// <returns>The template text.</returns>
private GameObject CreateTemplateText()
{
int fontSize = (int)(this.rectTransform.rect.height * 0.8);
var gameObject = new GameObject();
gameObject.name = "Template";
var text = gameObject.AddComponent<NumberText>();
text.color = this.textColor;
text.font = this.textFont;
text.fontSize = fontSize;
text.alignment = TextAnchor.MiddleCenter;
gameObject.SetActive(false);
gameObject.transform.SetParent(this.gameObject.transform);
return gameObject;
}
/// <summary>
/// 位置調整
/// </summary>
/// <param name="text">Text.</param>
/// <param name="value">Value.</param>
/// <param name="position">Position.</param>
private void AdjustRect(GameObject text, int value, int position)
{
var size = this.sizeList[value];
var rectTransform = text.gameObject.GetComponent<RectTransform>();
rectTransform.sizeDelta = size;
this.startX += (size.x * (position == 0 ? 0.5f : 1f));
rectTransform.localPosition = new Vector2(this.startX, 0);
}
/// <summary>
/// 各数字の横幅を一気に取得しておく
/// </summary>
private void PreLoadSize()
{
var generator = new TextGenerator();
var settings = this.template.GetComponent<Text>().GetGenerationSettings(Vector2.zero);
for (int i = 0; i < 10; i++) {
var width = generator.GetPreferredWidth(i.ToString(), settings);
this.sizeList.Add(new Vector2(width, this.rectTransform.rect.height));
}
}
}
class NumberText: Text
{
public void AnimateWave(float delay)
{
var rectTransform = this.gameObject.GetComponent<RectTransform>();
var seq = DOTween.Sequence();
seq.Append(rectTransform.DOLocalMoveY(5f, 0.2f).SetDelay(delay));
seq.Append(rectTransform.DOLocalMoveY(0f, 0.1f));
}
public void AnimateScale(float delay)
{
var rectTransform = this.gameObject.GetComponent<RectTransform>();
var seq = DOTween.Sequence();
seq.Append(rectTransform.DOScale(1.4f, 0.2f).SetDelay(delay));
seq.Append(rectTransform.DOScale(1f, 0.1f));
}
public void AnimateRotate(float delay)
{
var rectTransform = this.gameObject.GetComponent<RectTransform>();
rectTransform.DOLocalRotate(new Vector3(0, 360, 0), 0.4f, RotateMode.FastBeyond360)
.SetDelay(delay)
.OnComplete(() => {
rectTransform.localRotation = Quaternion.Euler(0, 0, 0);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment