[unity]簡単にエクセルとデータ連動する

エクセルは誰でも使えるデータ生成ツール

一部のプログラマーには嫌われることの多いエクセルですが、データ作成にあたっては様々な利点があります。

  • 入力が簡単で手早くできる
  • プログラマー以外でも大抵の人が使える
  • 計算式マクロやソート・フィルタが使えるのでデータを比較・検討することも容易

嫌われる1番の理由は Git や Svn などで履歴の比較が難しい点でしょうか。

ただ、このエクセルデータをそのまま unity ゲームに入れることは出来ません。
これを自動化するためのツール XlsToJson を紹介します。
ToJson としていますが、Scriptable Object にも対応しています。

以前紹介した ImportXLS の拡張ですが、随分変えてしまったので別のものとして紹介します。

unity でデータを作る方法

その前に、unity でデータを作る一般的な方法について簡単に説明します。

プログラムでデータクラスを作成する

例としてキャラクターのデータを作ります。

[System.Serializable]
public class Row
{
    public int       CharacterNo;
    public string    CharacterName;
    public float     Size;
    public List<int> FriendNo = new List<int>();
    public Sex       Sex;
}

キャラクター番号、名前、サイズ、友達の(キャラクター)番号、性別。
性別は enum で定義しています。

public enum Sex
{
    Female,
    Male,
    Unknown,
}

現実的なデータは int, string, float などの単純な型だけでなく、List や enum なども含まれるでしょう。
エクセルから手作業でデータを取り込んでいた場合、もうこの時点で面倒になるはずです。
ツールでは上記の宣言をエクセルから自動生成します。(DataClass)

Dictionary は対応していません。JsonUtility や ScriptableObject がそもそも Dictionary を許容してないためです。

Json 形式

データクラスが出来ていれば、json については JsonUtility で比較的簡単に読み書きが可能です。
他への転用も効きやすいですし、一番メジャーな形式ではないでしょうか。

var row = new Row()
{
    CharacterNo = 1,
    CharacterName = "Jsan",
    Size = 1.0f,
    Sex = Sex.Male
} 

// Json Text に変換
string jsontext = JsonUtility.FromJson<Row>(row, true);

// Text からデータに変換
var row2 = JsonUtility.ToJson(row);

JsonUtility では複数のデータを持ちたい場合に List が使えないため、ダミークラスを作ってその中に List のメンバーを作るという手間をかける必要があります。軽さゆえの制約?

[System.Serializable]
public class Wrapper
{
    public List<Row> Rows = new List<Row>();
}

var json = File.ReadAllText("sample.json", System.Text.Encoding.UTF8);
var data = JsonUtility.FromJson<Wrapper>(json);

Scriptable Object 形式

uinty 固有の形式でアクセスは速い(と、言われている)、インスペクタで確認・編集が可能という固定データ向きのフォーマットですが、読み込みはともかく書き出しが面倒です。
また、インスペクタでのみデータを編集するのも不安です。

XlsToJson ではデータ作成・編集は全てエクセルで行い、最終段階で ScriptableObject を自動書き出しするようにしています。

使い分け

考えるのが面倒であれば全て Json にしておくとデータ更新時の差分も取れていいかな? というのが個人的な感想です。
よほど大容量であれば Scriptable Object も悪くはなさそうです。
(XlsToJson を使う場合、インスペクタで編集可能な利点はありません。エクセルでより自由度の高いエディットが可能だからです)

XlsToJson

ダウンロード(リポジトリ)

unity のサンプルプロジェクトになっています。

サンプルプロジェクトの動作チェック

GitHub から取得した環境を unity で開きます。

Asset/Sample.xlsx(サンプルデータです)を右クリックし、XlsToJson Settings… を選択

デフォルト値のまま、左下の CREATE Importer ボタンを押します。

Asset/Class_Character.cs
Asset/Class_Stage.cs

データクラスの型を定義するコードです。
このクラスによって、エクセルの表を List<Row> という型で読み書きできるようにします。
(表は黄色い部分)

Asset/Character.cs
Asset/Stage.cs

先ほどの方法ではデータのインスタンス(data, data2)を管理する必要があり、少々面倒です。
Character.cs、Stage.cs はシングルトンインスタンスを内包しているので、どこからでもデータにアクセス可能になります。

Tools/XlsToJson/[Create] JsonData

Asset/Resources にエクセルで定義されたテーブルを Json Data として出力します。

Json を出力

[Create] ScriptableObject の場合、Scriptable Object が作成されます。

Json と ScriptableObject を出力

実際のコードでデータを表示してみる

ここからは、作成したデータの使い方。
Json と Scriptable Object 両方の使い方を提示します。[Create] JsonData[Create] ScriptableObject を事前に実行しておいてください。

Class_Character、Class_Stage クラスを使った表示の仕方

UsageTable.cs のコードを抜粋します。

(Json)
var jsontext = Resources.Load<TextAsset>("Data_Character");
var data = Class_Character.CreateInstance();
data.SetRowsByJson(jsontext.ToString());

foreach (var row in data.Rows)
{
    Debug.Log($"{row.ID} {row.CharacterName} {row.Sex}");
}
(Scriptable Object)
var obj = Resources.Load<Object>("Data_Character");
var data2 = obj as Class_Character;

foreach (var row in data2.Rows)
{
    Debug.Log($"{row.ID} {row.CharacterName} {row.Sex}");
}

適当な GameObject にアタッチし実行すると、コンソールで確認することができます。

Character、Stage クラスを使った表示の仕方

先ほどの方法ではデータのインスタンス(data, data2)を自前で管理する必要があり、実際に運用を始めると少々面倒です。
Character、Stage クラスはシングルトンインスタンスを内包しているので、どこからでもデータにアクセスできます。
コードの記述方法も、Json、Scriptable Object で同一となり、スッキリしています。

クラス Asset/UsageAccess.cs の抜粋です。
(ForEach の部分は前述の foreach と同じことを1行で書いただけ)

(Json)
var jsontext = Resources.Load<TextAsset>("Data_Character");
Character.SetTable(jsontext);
Character.Rows.ForEach( (row) => Debug.Log($"{row.ID} {row.CharacterName} {row.Sex}") );
(Scriptable Object)
var obj = Resources.Load<Object>("Data_Character");
Character.SetTable(obj);
Character.Rows.ForEach( (row) => Debug.Log($"{row.ID} {row.CharacterName} {row.Sex}") );

このクラスが不要な場合、作成をオフにすることもできます。

最低限の使用方法はこんなところです。
以下にもう少し詳しい使用方法について書いておくので、参考にしてください。

返信を残す

メールアドレスが公開されることはありません。

CAPTCHA