ゲームデータについて(5)テキストデータ

本記事ではテキストデータについて説明します。
システムメッセージデータとモンスターの名前データを作成するケースを例にとります。

テキストデータの外部ファイル化

テキストデータも固定データと同様に外部ファイル化します。
Assets/EditorにTextDataというディレクトリを作成してテキストデータを管理するエクセルファイルを用意します。
名前はtextData.xlsmとします。
fixedData.xlsxと異なりマクロありファイルにします。(理由は後述)
システムメッセージテキストをこんな感じで作成します。

シート名は"System"とします。
テキストを呼び出す際のIDとして、内容がわかりやすいように文字列で定義されたものを用意します。(B列)
これをラベルと呼ぶことにします。
モンスター名テキストも同様に作成します。シート名は"MonsterName"とします。

テキストデータクラスの生成

Assets/GameData/にTextDataというディレクトリを作成し、Assets/GameData/TextData/にTextData.csというファイルを作成します。

using System;
using System.Collections.Generic;

[Serializable]
public class TextData
{
    public List<string> TextList = new List<string>();

    public void Clear()
    {
        TextList.Clear();
    }
}
テキストデータのコンバータの作成

Assets/EditorにTextDataConverter.csというスクリプトを作成します。
textData.xlsmには複数のシートがありますが、各シートにつき1000ずつIDを割り振って、空いているID分はダミーデータを保持する形式にします。

using UnityEditor;
using UnityEngine;
using UnityEngine.Assertions;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using NPOI.XSSF.UserModel;
using NPOI.SS.UserModel;

#if UNITY_EDITOR

public class TextDataConverter : EditorWindow
{
    [ MenuItem( "Utility/Convert Text Data" ) ]
    public static void ShowWindow()
    {
        EditorWindow window = EditorWindow.GetWindow( typeof( TextDataConverter ) );
    }

    public void OnGUI()
    {
        if (GUI.Button(new Rect(8, 8, 120, 32), "Text Data"))
        {
            ConvertData();
        }
    }

    // Excelファイルのコンバートを開始/終了するシート.
    private const int SHEET_BEGIN = 0;
    private const int SHEET_END = 1;

    // Excelファイルのヘッダ行数.
    private const int ROW_HEADER_NUM = 1;
    // テキスト列.
    private const int COLUMN_TEXT = 2;
    // シートごとのテキスト数.
    private const int TEXT_NUM_PER_SHEET = 1000;


    public void ConvertData()
    {
        using (FileStream readFileStream = new FileStream("Assets/Editor/GameData/textData.xlsm", FileMode.Open, FileAccess.Read))
        {
            XSSFWorkbook book = new XSSFWorkbook(readFileStream);
            if (book == null)
            {
                Assert.IsTrue(false);
                return;
            }

            TextData data = new TextData();
            data.Clear();

            for (int i = SHEET_BEGIN; i <= SHEET_END; i++)
            {
                ISheet sheet = book.GetSheetAt(i);

                // シートのデータをTextDataに格納する.
                ConvertData(sheet, ref data);

            }

            byte[] serializedData = null;

            using (MemoryStream memoryStream = new MemoryStream())
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                binaryFormatter.Serialize(memoryStream, data);
                serializedData = memoryStream.ToArray();
            }

            using (FileStream serializeFile = new FileStream("Assets/ExternalResources/Resources/TextData/TextData.bytes", FileMode.Create))
            {
                serializeFile.Write(serializedData, 0, serializedData.Length);
            }
        }
    }

    public void ConvertData(ISheet Sheet, ref TextData OutData)
    {
        for (int i = ROW_HEADER_NUM; i < TEXT_NUM_PER_SHEET + ROW_HEADER_NUM; i++)
        {
            if (i <= Sheet.LastRowNum)
            {
                IRow row = Sheet.GetRow(i);
                ICell cell = row.GetCell(COLUMN_TEXT);
                if (cell == null)
                {
                    continue;
                }

                OutData.TextList.Add(row.GetCell(COLUMN_TEXT).StringCellValue);
            }
            else
            {
                // 空行にはダミーデータを追加.
                OutData.TextList.Add("");
            }
        }
    }
}

#endif // UNITY_EDITOR

コンバータを実行してファイルAssets/ExternalResources/Resources/TextData/TextData.bytesが出力されることを確認します。
次記事に続きます。