UnityでCSVを活用したメッセージウィンドウの作り方

ゲーム開発では、プレイヤーに重要な情報を伝えるためにメッセージウィンドウを頻繁に使います。
しかし、ゲーム内で表示するメッセージが増えてくると、それらを一つ一つ管理していくのは非常に大変な作業になります。
メッセージの内容を変更したい時や、新しいメッセージを追加したい時に、一つ一つのテキストを直接編集するのは時間がかかり、効率も良くありません。

こうした問題を解決する一つの方法が、CSVファイルを利用したメッセージ管理です。
CSVファイルを使えば、メッセージの編集や追加が簡単になり、開発がスムーズに進むようになります。

そこで今回は、UnityでCSVファイルを使ってメッセージを管理し、それをメッセージウィンドウで動的に表示する方法について詳しく解説します。
この方法を使えば、ゲーム内でのメッセージ管理がぐっと楽になります

またメッセージに限らずCSVはキャラクターのステータス管理などにも使えたりしますので、覚えておいて損はないと思います。

Unityスキルアップ、
始めるなら今

パズル、脱出、RPG...目標のゲームを完成させよう!

人気のUnity講座はこちら

Udemy講座

CSVについて

そもそもCSVについて知らない人のために簡単にどんなものか触れておきます。
CSVファイルとは、「comma separated values」の略称です。
値や項目をカンマ(,)で区切って書いたテキストファイル・データのこと指します。
具体的には以下のような内容のものになります。

key,message
welcome,ようこそゲームの世界へ!
quest_start,クエストを始めますか?
quest_complete,おめでとう!クエスト完了です!
thank_you,ご協力ありがとうございました。
goodbye,また会いましょう!

一行目は各列がそれぞれ何を示しているかを表すヘッダーと呼ばれるものです。
この場合は1行目にkeyが、2行目には実際に表示されるmessageが書かれています。
こういうデータをCSVといいます。
このフォーマットはExcelなどのスプレッドシートアプリケーションで開くことができ、データの編集や確認が簡単です。
ゲーム開発だけでなく、様々なデータ管理タスクにCSVが活用されています。

では続いて実際にUnityプロジェクトを立ち上げてCSVデータを表示させてみましょう。

メッセージ表示の準備

まず必要なものを色々と準備していきましょう今回必要なUIは以下のとおりです。

  • メッセージを表示するメッセージウィンドウ
  • メッセージ表示のトリガーとなるボタン

これだけになります。
では配置していきましょう。

UIの配置

まずメッセージウィンドウの背景になる画像を用意しておきましょう。
これは別の記事で紹介した9-sliceという方法で画像を分割しバックグラウンドとなるBGImageを配置しておきます。

BGImageを画面内に配置したらその子要素にTextを配置します。
続いてメッセージを表示させるためのボタンを配置しましょう。
今回は5種類のメッセージを表示させたいので5個のボタンを配置しておきます。
実際の画面はこんな感じになりました。
メッセージ表示用UI準備

続いてCSVファイルを配置したり、C#スクリプトを作成したりしていきます。

CSVファイルを扱う

早速CSVファイルをプロジェクトにインポートしましょう。

Resourcesフォルダ

ProjectウィンドウのAssets内にResourcesというフォルダを作ります。
Resourcesフォルダは、ゲーム実行時に動的にアクセス可能なアセットを格納する特別なフォルダです。
このフォルダ内に置かれたアセットは、スクリプトからResources.Load()メソッドを使って、ファイル名のみでロードできます。
Resourcesフォルダを使用することで、事前にシーンに配置しなくても、必要に応じてアセットを読み込み、使用することが可能になります。
但し注意も必要で、同じ名前で異なる形式のファイルが存在するとバグになる可能性があります。
必ずユニーク名前になるようにしておきましょう。
それでは今回は先程のCSVファイルを入れておきます。
sample.csvとしておきましょうか。

CSVファイルインポート

続いてCSVデータを読み込んだり、キーによってその内容を返す、MessageManagerというクラスを作っていきます。

CSV読込スクリプト作成

まず、Unityエディタ内のProjectビューでScriptsフォルダを作成しましょう。
これは、プロジェクト内のスクリプトを整理するためのものです。
次に、このScriptsフォルダ内で新しいC#スクリプトを作成し、そのスクリプトにMessageManagerという名前を付けます。
MessageManagerスクリプト作成

MessageManagerクラスは、直接ゲームオブジェクトにアタッチするタイプのクラスではありません。
そのため、このクラスはMonoBehaviourを継承する必要はありません
MessageManagerは単なるC#クラスとして定義しますが、UnityEngineの機能にアクセスしたい場合(例えばDebug.Logを使いたい場合)もあると思います。
その場合はクラスの先頭でUnityEngineネームスペースをusingディレクティブを使って明示的にインクルードしておきましょう。
初期のコードは以下の通りです。

using System.Collections.Generic;
using UnityEngine;

public class MessageManager{

}

続いてMessageManagerに実装するフィールドやメソッドを作っていきます。
まずCSVデータを読み込まないと何も始まりません。
LoadMessageというメソッドを作り、そこで実装していきます。
読み込んだデータをDictionaryで保持しておきたいのでそのフィールドも準備しておきましょう。

LoadMessageメソッド

具体的には以下のようになりました。

using System.Collections.Generic;
using UnityEngine;

public class MessageManager{
    public Dictionary<string, string> messages = new Dictionary<string, string>();
    
    public void LoadMessage(string fileName)
    {
        TextAsset textAsset = Resources.Load<TextAsset>(fileName);
        if(textAsset == null)
        {
            Debug.LogError("Faild to load the file");
            return;
        }

        string[] lines = textAsset.text.Split('\n');
        foreach(string line in lines)
        {
            if (!string.IsNullOrWhiteSpace(line))
            {
                string[] parts = line.Split(',');
                if(parts.Length == 2)
                {
                    messages[parts[0].Trim()] = parts[1].Trim();
                }
            }
        }
    }
}

処理の流れですが以下の通りになります。

・Resources.LoadメソッドでCSVファイルを読み込む。
※fileNameはResourcesフォルダ内のファイル名(拡張子無し)を指定
・TextAsset型の変数textAssetに代入する。
・textAssetのnullチェックを行う。
・textAssetを1行ずつに分割しstring型配列linesに格納する。
・linesを1行ずつlineに格納しforeachループで回す。
・IsNullOrWhiteSpaceメソッドでlineの中身をnullまたは空文字列かチェックする。
・lineをカンマ(,)で分割しstring型配列partsに格納する。
・partsの長さが2ならば辞書型messagesにキーと値を格納する。
・この時、キーと値はTrim関数で不要な余白を取り除く。

簡単ですがこんな感じの流れになっています。

続いてmessagesに格納した文字を取得するメソッドを作っていきましょう。

GetMessageメソッド

このメソッドはキーを受け取り、それに該当するmessages内の値を返すシンプルなメソッドです。

using System.Collections.Generic;
using UnityEngine;

public class MessageManager{
    /*略*/
    
    public string GetMessage(string key)
    {
        if (messages.ContainsKey(key))
        {
            return messages[key];
        }
        Debug.LogWarning($"Message key not found : {key}");
        return string.Empty;
    }
}

このように作ってみました。
messages.ContainsKey(key)でmessages内にキーが存在しているかをチェックし、存在している場合は値を返しています。
もしkeyが無ければ警告をログで表示し空の文字列を返しています。
nullではなく空の文字列を返している理由は、このメソッドの呼び出し元が常に文字列を受け取ることを想定しているためです。

CSVのヘッダー行をスキップ

これでOKと思いましたが、CSVデータは一行目がヘッダーの行なのでそれをスキップさせる仕組みをLoadMessageメソッドに入れましょう。
以下のように修正してみます。

using System.Collections.Generic;
using UnityEngine;

public class MessageManager{
    /*略*/
    
  public void LoadMessage(string fileName)
    {
        TextAsset textAsset = Resources.Load(fileName);
        if(textAsset == null)
        {
            Debug.LogError("Gaild to load the file");
            return;
        }

        string[] lines = textAsset.text.Split('\n');
        //追加 
        bool isHeaderLine = true;
        
        foreach(string line in lines)
        {
            //追加 
            if (isHeaderLine)
            {
                isHeaderLine = false;
                continue;
            }

            if (!string.IsNullOrWhiteSpace(line))
            {
                string[] parts = line.Split(',');
                if(parts.Length == 2)
                {
                    messages[parts[0].Trim()] = parts[1].Trim();
                }
            }
        }
    }
}

このような感じでbool値を使って一行目をスキップさせます。

次にこのクラスを呼び出しUIに表示する処理を書いていきましょう。

UIにデータを表示させる

ではUIにメッセージを表示させてみます。
MassageButtonというC#スクリプトを作成し、配置しているButtonにアタッチしておきましょう。

CSV読込のテスト

まずCSVデータが正常に読み込めるかテストしたいのでButtonをクリックしたらwelcomeがキーとなっているメッセージを表示させてみましょう。
コードは以下の通りです。

MessageManager Startメソッド

using UnityEngine;
using UnityEngine.UI;

public class MessageButton : MonoBehaviour
{
    public Text messageText;
    Button messageButton;
    MessageManager message;

    void Start()
    {
        messageButton = GetComponent<Button>();
        message = new MessageManager();
        message.LoadMessage("sample");
        messageButton.onClick.AddListener(()=> { messageText.text = message.GetMessage("welcome"); });
    }
}

流れは以下の通りです。

・必要なフィールドを準備する
・MessageTextをInspectorからアタッチする。
・自身のButtonコンポーネントを取得する。
・MessageManagerのインスタンスを生成する。
・sampleCSVを読み込む
・messageButtonがクリックされた処理を記述する。
※今回は固定でwelcomeがキーとなっているメッセージを表示させる。

では実際に起動し実験してみましょう。
ボタンのテスト

このようにボタンをクリックすると「ようこそゲームの世界へ!」と表示されました。

ボタン毎に表示メッセージを変える

今はすべてのボタンが同じkeyを呼び出していますので、これをそれぞれ変更してあげましょう。
MessageButtonにpublicでstrign keyを追加してあげます。
そしてMessageManagerのGetMessageメソッドにそのkeyを引数にして渡してあげます。

using UnityEngine;
using UnityEngine.UI;

public class MessageButton : MonoBehaviour
{
    public string key; //追加
    public Text messageText;
    Button messageButton;
    MessageManager message;

    void Start()
    {
        messageButton = GetComponent<Button>();
        message = new MessageManager();
        message.LoadMessage("sample");
        messageButton.onClick.AddListener(()=> { messageText.text = message.GetMessage(key); });
        
    }
}

このようにフィールドを増やし、それぞれのButtonのInspectorでkeyを設定してあげます。
ボタンにkeyを設定

それぞれにキーを設定したら再度テストしてみます。
ボタンにキーを振り分けてテスト

ボタン毎に表示されるメッセージが変わりました。
CSVからデータを取得しkeyとvalueのペアを作成してUIに反映させることが出来ました。
今回は非常にシンプルな使い方でしたが、冒頭でも触れたようにCSVは様々な使い道があると思いますので色々試してみてください。

また今回のCSVメッセージのプロジェクトはGithubに公開しておきます。
よかったら参考にしてみてください。
Githu CSV_Message_Sample

おすすめUnityオンライン学習

一人でゲーム開発が不安な方はオンラインスクールで学習すると効率が良いと思います。
以下に当てはまる人は検討してみると良いかもしれません。

「ゲーム作りけど何から初めればいい?」
「入門書をの次に何をしたらいいの?」
「疑問や問題を一人で解決出来ない。。」
「ゲームを完成させる自信がない。。」
「気軽に質問できる環境が欲しい。。」

自分で学習することに限界を感じたら
オンライン学習しましょう!

Udemy

Udemy
特徴:教材動画買い切り型
レッスン方法:動画教材/Q&Aで質問
習得スキル:教材動画によって異なる
コース概要: ピンポイントで作りたいゲームジャンルの動画を見つけることができるかもしれません。 また頻繁にセールを開催していますのでゲーム開発講座が1500円~で購入することも可能です。
ゲームジャンル別おすすめ講座はこちら Udemy 詳細

テックアカデミー

テックアカデミー
特徴:現役エンジニア伴走型レッスン
レッスン方法:チャット(週2回)/テキストチャット/課題レビュー
習得スキル:オリジナルゲームアプリの作成
コース概要: 途中で挫折しないためにメンター(相談者)が週2回、マンツーマンであなたの質問・相談に答えてくれるので、ゲーム開発・プログラミング未経験の人でも安心してゲーム開発に取り組めます。転職したい人向けのサポートもあります。無料体験もあります。
テックアカデミー 詳細

テックスタジアム

テックスタジアム
特徴:ゲーム開発の為のオンラインスクール
レッスン方法:動画教材,Slackでの質問(24時間)
習得スキル: Unity,UnrealEngine、CG、企画、サーバー、AI、XR等
コース概要: ゲーム業界で必須な技術の習得が可能です。Slack上で待機している先生への24時間、何度でも質問できます。またIT・ゲーム業界への就職サポートが無料で受けられます。
ゲーム開発に特化したオンラインスクールですので、Unityはもとより、他のゲームエンジンやゲーム業界に興味がある方にはオススメです。
テックスタジアム 詳細

デジハリONLINE

デジハリONLINE
特徴:動画カリキュラム型レッスン
レッスン方法:動画講座/Slack/予約制Zoom相談
習得スキル:Unity基礎,実践/ハイクオリティ3Dゲーム
コース概要: デジタルハリウッド大学・大学院などを通じたデジタルコンテンツ業界とのつながりを活かし、最新かつ実践的なカリキュラムを提供しています。【基礎編】【実践編】とカリキュラムが分かれていて、それぞれに課題があり、ご自身の理解度を把握できます。最終的にはハイクオリティの3Dゲームが作れるようになります。
デジハリONLINE 詳細

関連記事

最後までご覧頂いてありがとうございました。

セール中!
ノンフィールドRPG

基礎からリリースまで!

オリジナルRPGを作ってストアに公開しよう!