この記事でのバージョン
Unity 2018.3.4f1
はじめに
エクセルやスプレッドシートでデータをまとめて、
ScriptableObjectに変換して使うというのはUnityではよくあります。
実はその変換部分を自動でやってくれるアセット(?)の有名所に
Unity-Excel-ImporterとUnity-QuickSheetという2つがあります。
2つあるとなると、やはりどちらを使うか悩むので、
今回はその2つを実際に使い、比較をしてみた感じの記事です!
目次
- はじめに
- 目次
- 両者で出来ることと出来ない事、それぞれの良い所
- Unity-Excel-Importerの使い方
- Unity-QuickSheetの使い方(xlsファイルがプロジェクト内にある場合)
- Unity-QuickSheetの使い方(スプレッドシートからダウンロードしてくる場合)
- おわりに
両者で出来ることと出来ない事、それぞれの良い所
最初に分かりやすいように
両者で共通して出来る事と出来ない事、それぞれの良い所をを箇条書きにしてみました。
なお、詳細は次項以降の使い方で確認出来ると思います。
共通して出来る事
- xls(xlsxも?)ファイルからScriptableObjectのクラスを自動作成
- 変換処理を行うクラスも自動作成
- xlsファイルを更新するとScriptableObjectも自動更新
- シート毎に異なる形式のデータでも変換可能
共通して出来ない事
- ScriptableObjectファイルの生成場所の指定
Unity-Excel-Importerの良い所
- 日本語の解説がある
- クラス名や変数名をファイルとは別に設定可能
- 変換時に型を自動判定
- 複数のシートを1つのScriptableObjectにまとめる事が可能
Unity-QuickSheetの良い所
- 設定項目にshortやlong、Enumも使える
- 配列の設定が1列で出来る
- 生成されたScriptableObjectのInspectorがちょっと見やすい
- スプレッドシートのダウンロードがエディタ上で出来る
基本的には簡単に使えるUnity-Excel-Importerがオススメで、
shortやlong、Enumが使いたい場合や、
スプレッドシートのダウンロードを行いたい場合はUnity-QuickSheetがオススメになります。
ただし、Unity-QuickSheetはクラス名と変数名がファイルでの設定と必ず同じになるため、
例えば「ScriptableObjectではisBossだけど、エクセルでは"ボスならTRUE、それ以外はFALSE"」
のように説明用の名前を設定することが出来ず、
自分以外の人(特に非プログラマー)と一緒にやる場合は結構使いにくいと思われます。
Unity-Excel-Importerの使い方
まずはUnity-Excel-Importerの使い方からです。
なお、エクセルの内容はモンスターのパラメータのような2つのシートを作成し、
intやstring、floatにboolといった複数の型の項目を作ってあります。
また、配列を指定したい場合は項目名に[]を付けて列を分けて設定します。
GitHubから取得してくると、unitypackageが入ってるので、これで簡単にインポート出来ます。
インポートが完了したら、対象のxlsファイルを右クリックし、Create XLS Settingsを実行します。
すると、ウィンドウが表示されるので、ここで各種設定をします。
- class name : 変換後のScriptableObjectのクラス名(デフォルトはxlsファイルの名前)
- sepalate sheet : 有効にするとシートごとに別のScriptableObjectに分割します
- sheet settings : 変換するシートの設定
- parameter setting : 変換する項目とその型と変数名(自動で設定されるが、変更する事も可能)
なお、型にはbool, string, int, float, doubleとその配列が使えます。
設定後、xlsのファイルをReimportするか、保存を行うと、
xlsファイルと同じ場所にScriptableObjectが生成されます。
もちろん、xlsファイルを更新すれば、ScriptableObjectも更新されます。
また、ScriptableObjectや変換処理のプログラムはTerasurware/Class以下に生成されます。
今回の例で生成されたScriptableObjectのプログラムは以下の通りで、
using UnityEngine; using System.Collections; using System.Collections.Generic; public class Entity_Monster1 : ScriptableObject { public List<Sheet> sheets = new List<Sheet> (); [System.SerializableAttribute] public class Sheet { public string name = string.Empty; public List<Param> list = new List<Param>(); } [System.SerializableAttribute] public class Param { public double No; public string Key; public string Name_JP; public string Name_En; public float HP; public int ATK; public int DEF; public int[] ItemNoArray; public bool BOSS; } }
これを実際に使う場合にはこんな感じになると思います。
//生成されたScriptableObjectをInspectorで設定 public Entity_Monster1 MonsterData; private void Start(){ //各シートのデータを順に取り出す foreach (Entity_Monster1.Sheet monsterSheet in MonsterData.sheets) { //各項目のデータを順に取り出す foreach (Entity_Monster1.Param monsterParam in monsterSheet.list) { //モンスターの日本語名をログで表示 Debug.Log(monsterParam.Name_JP); } } }
今回は同じデータ形式のシートが複数あるタイプでしたが、
別のデータ形式のシートが複数あるタイプを変換するUnity-Excel-Importerもあります。
例えばモンスターデータとアイテムデータを1つのエクセルで管理したい場合などに使えます。
なお、最初に紹介したリポジトリとは別のリポジトリになるので注意が必要です。
Unity-QuickSheetの使い方(xlsファイルがプロジェクト内にある場合)
次にUnity-QuickSheetのxlsファイルがプロジェクト内にある場合の使い方です。
なお、エクセルの内容はUnity-Excel-Importer時と基本的に同じですが、
ImprintTypeというenumが追加されています。
また、配列は1つの列にカンマ区切りで設定します。
GitHubから取得したら、Assets以下にあるQuickSheetをプロジェクトにそのまま追加します。
その後、QuickSheet -> Tools -> Excelからファイルを作成、
作成したファイルを選択し、Inspector上でxlsファイルを指定し、Importを実行
すると、各項目が表示されるので型を自分で指定します。(配列の場合はArrayにチェック)
なお、クラス名や変数名は変更できません。(エクセルでの設定がそのまま反映される)
型の種類にはstring, short, int, long, float, double, enum, boolが使えます。
ただし、enumを使いたい場合は先にenumを宣言しておく必要があります。
(今回の例だとImprintTypeというenumを先に宣言)
public enum ImprintType { Cute, Smart, Cool }
項目の設定が済んだら、パスの設定をし、Generateボタンを押します。
すると指定したパスにスクリプトが生成されます。
生成されるのは指定した1つのシート分だけなので、
複数のシートがある場合はWorksheetを切り替えて、再度Generateする必要があります。
(Monster1(Data)とMonster2(Data)はクラス名以外同じ内容になる)
また、シートのデータ形式を変える場合は設定ファイルも別にする必要があります。
(Monster1とMonster2で項目の種類が違う場合など)
設定後、xlsのファイルをReimportするか、保存を行うと、
xlsファイルと同じ場所にScriptableObjectが生成されます。
もちろん、xlsファイルを更新すれば、ScriptableObjectも更新されます。
(ScriptableObjectのUpdateボタンで更新する事も可能)
ちなみに、今回生成されたクラスのプログラムは以下のような感じで、
using UnityEngine; using System; using System.Collections; using System.Collections.Generic; /// /// !!! Machine generated code !!! /// /// A class which deriveds ScritableObject class so all its data /// can be serialized onto an asset data file. /// [System.Serializable] public class Monster1 : ScriptableObject { [HideInInspector] [SerializeField] public string SheetName = ""; [HideInInspector] [SerializeField] public string WorksheetName = ""; // Note: initialize in OnEnable() not here. public Monster1Data[] dataArray; void OnEnable() { //#if UNITY_EDITOR //hideFlags = HideFlags.DontSave; //#endif // Important: // It should be checked an initialization of any collection data before it is initialized. // Without this check, the array collection which already has its data get to be null // because OnEnable is called whenever Unity builds. // if (dataArray == null) dataArray = new Monster1Data[0]; } // // Highly recommand to use LINQ to query the data sources. // }
using UnityEngine; using System.Collections; /// /// !!! Machine generated code !!! /// !!! DO NOT CHANGE Tabs to Spaces !!! /// [System.Serializable] public class Monster1Data { [SerializeField] int no; public int No { get {return no; } set { no = value;} } [SerializeField] string key; public string Key { get {return key; } set { key = value;} } [SerializeField] string name_jp; public string Name_JP { get {return name_jp; } set { name_jp = value;} } [SerializeField] string name_en; public string Name_En { get {return name_en; } set { name_en = value;} } [SerializeField] float hp; public float HP { get {return hp; } set { hp = value;} } [SerializeField] int atk; public int ATK { get {return atk; } set { atk = value;} } [SerializeField] int def; public int DEF { get {return def; } set { def = value;} } [SerializeField] int[] itemnoarray = new int[0]; public int[] Itemnoarray { get {return itemnoarray; } set { itemnoarray = value;} } [SerializeField] ImprintType imprinttype; public ImprintType IMPRINTTYPE { get {return imprinttype; } set { imprinttype = value;} } [SerializeField] bool boss; public bool BOSS { get {return boss; } set { boss = value;} } }
実際に使う場合はこんな感じになると思います。
//生成されたScriptableObjectをInspectorで設定 public Monster1 Monster1; private void Start(){ //各項目のデータを順に取り出す foreach (Monster1Data monster1Data in Monster1.dataArray) { //モンスターの日本語名をログで表示 Debug.Log(monster1Data.Name_JP); } }
Unity-QuickSheetの使い方(スプレッドシートからダウンロードしてくる場合)
最後にUnity-QuickSheetのスプレッドシートからダウンロードしてくる場合の使い方です。
(xlsファイルがプロジェクト内にある場合とリポジトリは同じ)
なお、xlsファイルがプロジェクト内にある場合と同じデータをスプレッドシートに作成しています。
まずはスプレッドシートを作ったのと同じアカウントで、
Google Developer Console(Google Cloud Platformと同じ?)にアクセスします。
ここでダッシュボードの左上の項目から、新しいプロジェクトを作成し、
認証情報の同意画面を作成します。
(とりあえずアプリケーション名だけ設定して、保存でOK)
その後、認証情報からOAuth クライアント IDの作成を行います。
ここで、クライアントID&シークレットが表示されますが、これを無視して、
jsonをダウンロードし、プロジェクトに追加します。
ここからプロジェクトに戻り、QuickSheet/GDataPlugin/Google Data Settingsを選択し、
Json設定をした後(IDとSecretは自動で設定)、Start Authenticationを実行、
ブラウザで権限の許可を求められるので、これを許可。
すると、アクセスコードが発行されるので、これをAccessCodeにコピペし、
Finish Authenticationを実行します。
ついでにパスも設定しておきます。
今度はQuickSheet/Tools/Googleを選択し、
作成されたImport Settingsに
変換したいスプレッドシートとワークシートの名前を設定し、Importを実行します。
あとはxlsファイルがプロジェクト内にある場合と同様に項目の設定をし、Generateを実行し、
プログラムが生成されます。
すると、Google/Monster1という項目が追加されるので、これで、ScriptableObjectを作成。
(Mosnter1はクラス名)
このScriptableObjectにはDownloadボタンがあるので、ここを押せばデータがロード&変換されます。
(スプレッドシート自体はプロジェクトに保存されない)
なお、ScriptableObjectの使い方は前項と同じなので割愛します。
おわりに
記事の通り、どちらも便利なのは間違いないですが、
場合によってはちょっと痒い所に手が届かないという事にもなりそうな感じでした。
もし、どうしてもこの2つでは満足できないという場合はおそらくこれらを改良するより、
普通に専用の変換処理とScriptableObjectのクラスを作った方が楽かと思います。
今回紹介した2つのように汎用的なやつを作るのは大変ですが、
専用のやつを作るのはそんなに大変じゃなかったりするので。
(もしかしたらこのへんも記事にするかも)