UNET③ ログをゲーム画面上に表示

今回はログをゲーム画面上に表示する機能を作ります。

f:id:motoyamablog:20171028011843g:plain

 いつまで経ってもUNETの使い方が始まらないので、驚いているかと思います。私も驚いています。
しかし、準備が重要なのです。UNETというそれなりに複雑怪奇なシステムに立ち向かうには、こちらもそれなりの準備が必要です。さもなくば、作ったゲームはぐちゃぐちゃになり、わけのわからない挙動を行い、プロジェクトは頓挫するでしょう(そのような学生のプロジェクトをいくつも見てきました😢)

何故、ログをゲーム画面上に表示する必要があるのか?

UNETでネットワークゲームを開発する場合、動作確認が面倒です。なにせ、ネットワークゲームなので、ゲームが最低2つは起動していなければなりません。では、どのようにその状況を作るのか?
大抵は以下のように動作確認を行います。

  1. ゲームの実行ファイル(exe)をビルド
  2. exeを起動する
  3. Unityエディター上でもゲームを起動する
  4. exeとエディターで通信させて動作確認する

この方法を使えば、1台のPCでネットワークゲームの動作確認ができます。ちゃんと複数の端末を使って動作確認したほうがより好ましいですが、面倒なので、ちょっとした動作確認は上記の方法で済ませ、本気で動作確認する場合は複数の端末を使うなどします。

で、上記の方法で確認する際、exeから起動したゲームのログが見れないのが不便なのです(ログファイルに出力されてますが、いちいち開いて見るのは面倒です)。

というわけで、exeのほうでも簡単にログを確認できるように、ログをゲーム画面上に表示する機能を作ります!

ログをゲーム画面上に表示する機能を作る

では面倒くさからずに作りましょう。一度作っておけば、他のプロジェクトでも使いまわしがききます。スマホ向けのプロジェクトでも有用と思われます。

適当に空のオブジェクトを生成し、名前は「LogDisplay」などとします。
で、新規スクリプトを作成してアタッチします。スクリプト名も「LogDisplay」とします。

using System.Collections;
using System.Collections.Generic; // Queueのために必要
using UnityEngine;
using System.Text; // StringBuilderのために必要

public class LogDisplay : MonoBehaviour
{
    // ログを何個まで保持するか
    [SerializeField] int m_MaxLogCount = 20;

    // 表示領域
    [SerializeField] Rect m_Area = new Rect(220, 0, 400, 400);

    // ログの文字列を入れておくためのQueue
    Queue<string> m_LogMessages = new Queue<string>();

    // ログの文字列を結合するのに使う
    StringBuilder m_StringBuilder = new StringBuilder();
 
    void Start()
    {
        // Application.logMessageReceivedに関数を登録しておくと、
        // ログが出力される際に呼んでくれる
        Application.logMessageReceived += LogReceived;
    }

    // ログが出力される際に呼んでもらう関数
    void LogReceived(string text, string stackTrace, LogType type)
    {
        // ログをQueueに追加
        m_LogMessages.Enqueue(text);

        // ログの個数が上限を超えていたら、最古のものを削除する
        while(m_LogMessages.Count > m_MaxLogCount)
        {
            m_LogMessages.Dequeue();
        }
    }

    void OnGUI()
    {
        // StringBuilderの内容をリセット
        m_StringBuilder.Length = 0;

        // ログの文字列を結合する(1個ごとに末尾に改行を追加)
        foreach (string s in m_LogMessages)
        {
            m_StringBuilder.Append(s).Append(System.Environment.NewLine);
        }

        // 画面に表示
        GUI.Label(m_Area, m_StringBuilder.ToString());
    }
}

あくまでデバッグ用の表示であり、また、多数のプロジェクトで気楽に使いまわしたいので、UGUIなどではなく、GUI.Labelを使って表示を行っています。
StringBuilderをフィールドとして持っている理由としては、そのほうがガベージコレクション減ると思いましたので。

使ってみる

早速使ってみましょう。適当に空のオブジェクトを作って、下記のような適当なスクリプトをアタッチして動かしてみましょう。

using UnityEngine;

public class LogDisplayTest : MonoBehaviour
{
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Z))
            print("Zを押しました");
        if (Input.GetKeyDown(KeyCode.X))
            Debug.Log("Xを押しました");
        if (Input.GetKeyDown(KeyCode.C))
            Debug.LogWarning("Cを押しました");
    }
}

 

f:id:motoyamablog:20171028011843g:plain

このようにログが出ましたか?
今回作ったLogDisplay.csスクリプトは、他のプロジェクトにも放り込むだけで使えるので、大事に取っておきましょう👍

あ、今回は使っていませんが、Application.logMessageReceivedに登録した関数の第2引数にはスタックトレースが、第3引数にはログの種類が渡されてきます。必要に応じてこれらも画面に出力するように改造すると、より便利になるかもしれません😃

 

次へ進む

目次へ