園児ニアのメモ

ただのエンジニア。何でも屋みたいな扱い受けてます。

【Unity】数字の画像でスコアを表現する

スコアなどを表示するときにフォントがあれば一番ですが、特殊な表示をしたい場合について書きます。

用意した0〜9の数字の画像を使ってそれをUI.Textのように簡単に使えるようにしてみたいと思います。

画像素材の用意

用意するのはこのような画像で0〜9までです。
f:id:nanokanato:20170908135201p:plain:w30

スクリプトの用意

以下のNumberText.csはUI.Textのように簡単な入力で画像を使ったスコアなどの表示をするためのクラスです。

このスクリプトを空のGameObjectに配置することで使用できます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class NumberText : MonoBehaviour {
	public long num = 1234567890;
	public int digit = 16;
	public bool zeroFill = false;
	private List<Image> NumImageList = new List<Image>();
	[SerializeField] private Sprite[] spriteNumbers = new Sprite[10];
	
	// Update is called once per frame
	void Update () {
		if (NumImageList.Count == digit) {
			//桁数が揃っているので数値を表示する
			long num2 = num;
			int numDigit = 0;
			if (num2 > 0) {
				numDigit = ((int)Mathf.Log10(num2) + 1);
			}
			if (numDigit > digit) {
				//数値が桁数を超えている
				for (int i = 0; i < NumImageList.Count; i++) {
					Image numImage = NumImageList.ToArray () [i];
					if (numImage != null) {
						numImage.color = Color.white;
						numImage.sprite = spriteNumbers [spriteNumbers.Length - 1];
					}
				}
			} else {
				//数値が桁数を超えていない
				int[] numIndexs = new int[numDigit];
				for (int i = 0; i < numDigit; i++) {
					numIndexs [i] = (int)(num2 % 10); 
					num2 = num2 / 10;
				}
				for (int i = 0; i < NumImageList.Count; i++) {
					Image numImage = NumImageList.ToArray()[i];
					if (numImage != null) {
                                                if (numDigit == 0 && i == 0) {
							//数値が0だった時の処理(1桁目は必ず0で表示)
							numImage.color = Color.white;
							numImage.sprite = spriteNumbers[0];
						} else if (i < numIndexs.Length) {
							//数値を反映する
							numImage.color = Color.white;
							numImage.sprite = spriteNumbers[numIndexs[i]];
						} else {
							if (zeroFill) {
								//0埋め
								numImage.color = Color.white;
								numImage.sprite = spriteNumbers[0];
							} else {
								//非表示
								numImage.color = Color.clear;
							}
						}
					}
				}
			}
		} else {
			if (NumImageList.Count < digit) {
				//桁数が足りないので増やす
				GameObject numImageObj = new GameObject();
				if (numImageObj != null) {
					numImageObj.name = "NumberImage"+(NumImageList.Count+1);
					numImageObj.transform.SetParent (this.transform);
					RectTransform thisRect = this.GetComponent<RectTransform> ();
					if (thisRect != null) {
						Image numImage = numImageObj.AddComponent<Image> ();
						if (numImage != null) {
							numImage.color = Color.clear;
							RectTransform numImageRect = numImageObj.GetComponent<RectTransform> ();
							if (numImageRect != null) {
								if (spriteNumbers != null && spriteNumbers.Length > 0) {
									numImageRect.sizeDelta = new Vector2(spriteNumbers[0].bounds.size.x*(thisRect.sizeDelta.y/spriteNumbers[0].bounds.size.y), thisRect.sizeDelta.y);
									if (NumImageList.Count == 0) {
										numImageObj.transform.localPosition = new Vector3 (thisRect.sizeDelta.x / 2 - numImageRect.sizeDelta.x / 2, 0);
									} else {
										Image image = NumImageList.ToArray () [NumImageList.Count - 1];
										if (image != null) {
											numImageObj.transform.localPosition = new Vector3 (image.transform.localPosition.x - numImageRect.sizeDelta.x, 0);
										}
									}
									NumImageList.Add (numImage);
								}
							}
						}
					}
				}
			} else {
				//桁数が多いので減らす
				Image image = NumImageList.ToArray()[NumImageList.Count-1];
				if (image != null) {
					NumImageList.RemoveAt(NumImageList.Count-1);
					Destroy(image.gameObject);
				}
			}
		}
	}
}

中にコメントが書いているので何をしているかわかると思いますが説明。

主な設定項目
  • num - 表示したい数値
  • digit - 表示する最大桁数
    • numがdigitの桁数を超えた場合はdigitの桁数の最大の数値を表示する。(digitが4の時、9999など)
  • zeroFill - numがdigitの桁数より小さい場合に0埋めするかどうか
    • デフォルトはfalse、0埋めしない。
  • spriteNumbers - 0〜9までの数値の画像。
    • 0〜9の順番に合うように設定してください。
中でやっている処理について
  1. NumImageList(UI.Imageの配列)の数がdigit(最大桁数)と違う時、同じ桁になるようにUI.Imageを生成したり消したりする。
  2. NumImageListとdigitの桁数が同じになった時、numの桁数を計算する(計算結果:numDigit)
  3. numDigitがdigitより大きい時、digitの桁数で最大の数値を表示。
  4. numDigitがdigit以下の時、桁ごとの数値を取得する。(123の場合は1桁目が3、2桁目が2、3桁目が1など)
  5. 1桁目からNumImageListの同じ桁の位置のUI.Imageに画像を反映する。
  6. numDigitより大きい桁の場合、zeroFillがtrueなら0埋めする。falseなら非表示にする。

実際の表示

最大桁数内で0埋めしないパターン

f:id:nanokanato:20170908141411p:plain:w300
num:1234567890
digit:13
zeroFill:false

最大桁数が3桁分余ったので0埋めしたパターン

f:id:nanokanato:20170908141356p:plain:w300
num:1234567890
digit:13
zeroFill:true

最大桁数が少ないため最大値を表示したパターン

f:id:nanokanato:20170908141421p:plain:w300
num:1234567890
digit:9
zeroFill:false