2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Unity】便利なメッセージウィンドウを作る

Last updated at Posted at 2022-08-19

1. 概要

簡単に呼び出せるメッセージウィンドウを作りたい
具体的には以下の通り

  • メソッドだけで呼び出せる(GetComponentなどが不要)
  • テキストと表示時間を指定できる
  • 初期状態は非表示
  • 呼び出されると勝手に表示されて、秒数経過で勝手に消える

2. 作成したもの

1000カウント毎に「Push!!!」と書かれたメッセージウィンドウが表示され、1秒後に消える
ezgif.com-gif-maker (1).gif

3. 実装

Unity側

デモの作成にはUnity 2021.3.6を使用した
ヒエラルキーは以下の通り
image.png

  • Image:メッセージウィンドウそのもの
  • Image下のText(TMP):メッセージ
  • Canvas下のText(TMP);カウント表示用

全てヒエラルキーを右クリック→「UI」から生成

スクリプト

MessageWindow.csを作成→Imageにアタッチする

MessageWindow.cs
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class MessageWindow : MonoBehaviour
{
	public static MessageWindow instance;

	Coroutine coroutine;
	bool isRunning = false;

	GameObject textWindow;
	TextMeshProUGUI text;

	private void Awake() {
		if(instance == null) {
			instance = this;
		} else {
			Destroy(gameObject);
		}
	}

    // 初期化
	void Start()
    {
		textWindow = this.gameObject;
		text = textWindow.transform.GetChild(0).GetComponent<TextMeshProUGUI>();
		DisableTextWindow();
    }

    // このメソッドを呼び出してメッセージウィンドウを更新する
	public void SetMessage(string str, float sec) {
		if (isRunning) {
			StopCoroutine(coroutine);
			coroutine = null;
		}

		coroutine = StartCoroutine(UpdateMessageWindow(str, sec));
	}

    // メッセージウィンドウの更新をコルーチンで実装
	private IEnumerator UpdateMessageWindow(string str, float sec) {
		isRunning = true;
		text.text = str;

		EnableTextWindow();

		yield return new WaitForSeconds(sec);

		DisableTextWindow();
		isRunning = false;
	}

    // メッセージウィンドウを表示する
	private void EnableTextWindow() {
		Image img = textWindow.GetComponent<Image>();
		img.color = new Color(img.color.r, img.color.g, img.color.b, 1);
		text.color = new Color(text.color.r, text.color.g, text.color.b, 1);
	}

    // メッセージウィンドウを非表示にする
	private void DisableTextWindow() {
		Image img = textWindow.GetComponent<Image>();
		img.color = new Color(img.color.r, img.color.g, img.color.b, 0);
		text.color = new Color(text.color.r, text.color.g, text.color.b, 0);
	}
}

解説

  • シングルトン
    MessageWindowクラスはシングルトンとして実装している
    該当コードは以下
MessageWindow.cs
public static MessageWindow instance;

// (中略)

private void Awake() {
	if(instance == null) {
		instance = this;
	} else {
		Destroy(gameObject);
	}
}

シングルトンはデザインパターンの一種で、シーン内に1つしか存在しないインスタンスである
自身をstaticのインスタンスとして持ち、すでにインスタンスとして存在している場合は自身を破棄することで実現している
参考([Unity]シングルトンを使ってみよう)

  • Start メソッド
    初期化処理
    Unityでの操作を減らすため、アタッチされたオブジェクトからGetComponentでオブジェクトを取得する
    (ただこうするとヒエラルキー側の変更に対応できない...)
    DisableTextWindowメソッドで非表示にしておく
MessageWindow.cs
void Start()
    {
		textWindow = this.gameObject;
		text = textWindow.transform.GetChild(0).GetComponent<TextMeshProUGUI>();
		DisableTextWindow();
    }
  • EnableTextWindow / DisableTextWindow メソッド
    Imageコンポーネントを取得→ウィンドウのImageとテキストのColorを再設定している
    new Color(r, g, b, a)aが不透明度に対応している
MessageWindow.cs
private void EnableTextWindow() {
	Image img = textWindow.GetComponent<Image>();
	img.color = new Color(img.color.r, img.color.g, img.color.b, 1);
	text.color = new Color(text.color.r, text.color.g, text.color.b, 1);
}

private void DisableTextWindow() {
	Image img = textWindow.GetComponent<Image>();
	img.color = new Color(img.color.r, img.color.g, img.color.b, 0);
	text.color = new Color(text.color.r, text.color.g, text.color.b, 0);
}
  • UpdateMessageWindow メソッド
    引数にstr(メッセージ)sec(表示時間[s])を渡す
    コルーチンとして実装しており、yield return new WaitForSeconds(sec);で指定秒数処理を止める
MessageWindow.cs
private IEnumerator UpdateMessageWindow(string str, float sec) {
	isRunning = true;
	text.text = str;

	EnableTextWindow();

	yield return new WaitForSeconds(sec);

	DisableTextWindow();
	isRunning = false;
}
  • SetMessage メソッド
    引数にstr(メッセージ)sec(表示時間[s])を渡す
    isRunningは、UpdateMessageWindowコルーチンが実行中かどうか判定している
    どこからでも呼び出すことができるため、衝突した場合は実行中のコルーチンを停止させて新しいコルーチンを開始する
MessageWindow.cs
public void SetMessage(string str, float sec) {
	if (isRunning) {
		StopCoroutine(coroutine);
		coroutine = null;
	}

	coroutine = StartCoroutine(UpdateMessageWindow(str, sec));
}

4. つかいかた

呼び出すときは次の1行でどこからでも呼び出すことができる

MessageWindow.instance.SetMessage(str, sec);

TestScript.cs
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

public class TestScript : MonoBehaviour
{

	[SerializeField] TextMeshProUGUI text;
	int count;


    // Update is called once per frame
    void Update()
    {
		count++;
		text.text = "Count:" + count + "\n";

		if(count % 1000 == 0) {
			MessageWindow.instance.SetMessage("Push!!!", 1f);
		}
    }
}

1000カウント毎にSetMessageメソッドを呼び出している

おわりに

便利なテキストウィンドウを作ってみた
Imageに画像を設定しても動作するのでぜひ使ってみてほしい

(拡張性とかはあまり考えてないので、色々試してみてほしかったり)

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?