[Unity]エクセルでのデータ管理


はじめに

Unity1週間ゲームジャム「あつめる」でのExcelDataReader実践導入を例に記事を書いています。

また、管理クラスはUnity1週間ゲームジャム前に完成していましたがそちらも軽く説明を書いています。

お題「あつめる」

https://unityroom.com/unity1weeks/13

投稿作品「たこ焼きパーティー」

https://unityroom.com/games/takoyaki_party

ソースコード

https://gitlab.com/blueback28/unityroom_takoyaki


投稿作品での使用ライセンス等

Fee、自作ライブラリ

https://github.com/bluebackblue/fee_core

ExcelDataReader

https://github.com/ExcelDataReader/ExcelDataReader/

M+ FONTS

http://mplus-fonts.osdn.jp/

効果音ラボ

https://soundeffect-lab.info/

音楽:魔王魂

https://maoudamashii.jokersounds.com


ExcelDataReaderの導入

ExcelDataReaderをUnityで使用する方法はいくつかあります。

(nupkgの拡張子をzipに変えて中身を取り出す等)。

今回は以下のサイトをチェックアウトし、ビルドしました。

https://github.com/ExcelDataReader/ExcelDataReader/

必要そうなものをUnityに追加、追加するフォルダは「Plugins」

image.png


制御クラス


Fee.Excel

「ExcelDataReader」あるいは「NPOI」を使って決められた書式のエクセルをJsonとしてロードします。

今回は「ExcelDataReader」を使用しました。

https://github.com/bluebackblue/fee_core/tree/master/Script/Excel


Fee.JsonSheet

Json化したエクセルを解析し、データコンバートを行います。

この記事ではここの説明がメインになります。

https://github.com/bluebackblue/fee_core/tree/master/Script/JsonSheet


メニューへの追加

image.png

コンバート手順等はエクセルに記述します。

/** Convert

*/

#if(UNITY_EDITOR)
public class Convert
{
/** 全部。
*/

[UnityEditor.MenuItem("Takoyaki/Convert/All")]
public static void MenuItem_Convert_All()
{
//ログ。
Fee.Excel.Config.LOG_ENABLE = true;
Fee.JsonSheet.Config.LOG_ENABLE = true;

//エクセルをJSONシートにコンバート。
Fee.Excel.ExcelToJsonSheet t_exceltojsonsheet = new Fee.Excel.ExcelToJsonSheet();
if(t_exceltojsonsheet.Convert(Fee.File.Path.CreateAssetsPath("/Editor/Excel/convert.xlsx")) == false){
return;
}

//JSONシート取得。
Fee.JsonItem.JsonItem t_jsonsheet = t_exceltojsonsheet.GetJsonSheet();
if(t_jsonsheet == null){
return;
}

//コンバート。
Fee.JsonSheet.JsonSheet.ConvertFromJsonSheet(t_jsonsheet);

//ログ。
UnityEngine.Debug.Log("Convert_All");
}
}
#endif


各シートの説明


convert

「*」印が付いている項目を上から順番にコンバートしていきます。

今回はアセットバンドルは使用しないので「*」印を外しています。

image.png


se_command_list

「*」印が付いている項目を「se.prefab」「Data_SeCommonType.cs」として出力しています。

ENUMシートとオーディオシートの混合シートです。

image.png

/** Game.Data

*/

namespace Game.Data
{
/** 自動生成。
*/

public enum SeCommonType
{
/** マヨヒット
*/

MayoHit,

/** システム、決定
*/

Decide,

/** キッチン、「カッカッカッ」
*/

Right,

/** キッチン、「キーン」
*/

Left,

/** ワサビヒット
*/

WasabiHit,

/** 声「いっただっきまーす」
*/

Itadakimasu,

/** キッチン、「カタ」
*/

Cancel,

}
}


bgm_list

「*」印が付いている項目を「bgm.prefab」「Data_BgmType.cs」として出力しています。

ENUMシートとオーディオシートの混合シートです。

image.png

/** Game.Data

*/

namespace Game.Data
{
/** 自動生成。
*/

public enum BgmType
{
/**
*/

Title,

/**
*/

Main,

}
}


data_list

「*」印が付いている項目を「datalist.json」として出力しています。

データシートです。

image.png


text_id

「*」印が付いている項目を「text_id.json」として出力しています。

JSONシートです。

image.png


「datalist.json」からSE,BGM、テクスチャーをロードするコード

たいした量ではなかったのでベタ書きで一括全ロード。

//パス登録。

{
UnityEngine.TextAsset t_textasset = UnityEngine.Resources.Load<UnityEngine.TextAsset>(Config.Resources.PATH_DATALIST);
if(t_textasset != null){
string t_text = t_textasset.text;
if(t_text != null){
System.Collections.Generic.Dictionary<string,Fee.Data.JsonListItem> t_data_list = Fee.JsonItem.Convert.JsonStringToObject<System.Collections.Generic.Dictionary<string,Fee.Data.JsonListItem>>(t_text);
if(t_data_list != null){
Fee.Data.Data.GetInstance().RegisterDataList(t_data_list);
}else{
Tool.Assert(false);
}
}else{
Tool.Assert(false);
}
}else{
Tool.Assert(false);
}
}

//t_id
string[] t_id = new string[]{
"TAKOYAKI1",
"TAKOYAKI2",
"TAKOYAKI3",
"WASABI",
"MAYO",
"GAMEEND_WINDOW",
"BUTTON",
"SLIDER_BUTTON",
"SLIDER_BAR",

"SE_COMMON",
"BGM",
"TEXTID",
};

//ロード。
for(int ii=0;ii<t_id.Length;ii++){
Fee.Data.Item t_item = Fee.Data.Data.GetInstance().RequestLoad(t_id[ii]);

do{
yield return null;
}while(t_item.IsBusy() == true);

switch(t_id[ii]){
case "TAKOYAKI1":
{
if(t_item.GetResultAssetTexture() != null){
this.takoyaki1 = t_item.GetResultAssetTexture();
continue;
}
}break;

・・・略

case "SE_COMMON":
{
if(t_item.GetResultAssetPrefab() != null){
UnityEngine.GameObject t_prefab = t_item.GetResultAssetPrefab();
if(t_prefab != null){
Fee.Audio.Pack_AudioClip t_pack_audioclip = t_prefab.GetComponent<Fee.Audio.Pack_AudioClip>();
if(t_pack_audioclip != null){
Fee.Audio.Audio.GetInstance().LoadSe(t_pack_audioclip,SEID_COMMON);
continue;
}else{
Tool.Assert(false);
}
}else{
Tool.Assert(false);
}
}else{
Tool.Assert(false);
}
}break;
case "BGM":
{
if(t_item.GetResultAssetPrefab() != null){
UnityEngine.GameObject t_prefab = t_item.GetResultAssetPrefab();
if(t_prefab != null){
Fee.Audio.Pack_AudioClip t_pack_audioclip = t_prefab.GetComponent<Fee.Audio.Pack_AudioClip>();
if(t_pack_audioclip != null){
Fee.Audio.Audio.GetInstance().LoadBgm(t_pack_audioclip);
continue;
}else{
Tool.Assert(false);
}
}else{
Tool.Assert(false);
}
}else{
Tool.Assert(false);
}
}break;
case "TEXTID":
{
if(t_item.GetResultAssetText() != null){
System.Collections.Generic.List<TextId_ListItem> t_list = Fee.JsonItem.Convert.JsonStringToObject<System.Collections.Generic.List<TextId_ListItem>>(t_item.GetResultAssetText());
if(t_list != null){
this.textid_list = new System.Collections.Generic.Dictionary<string,string>();
for(int jj=0;jj<t_list.Count;jj++){
this.textid_list.Add(t_list[jj].id,t_list[jj].text);
}
continue;
}else{
Tool.Assert(false);
}
}else{
Tool.Assert(false);
}
}break;
}

Tool.Assert(false);
}


ロードしたデータを使用


BGM再生

「Data.BgmType.Title」はコンバート時に生成され、データパスはエクセルで設定できる。


//BGM再生。
Fee.Audio.Audio.GetInstance().PlayBgm(Data.BgmType.Title);


SE再生

「Game.Data.SeCommonType.Cancel」はコンバート時に生成され、データパスはエクセルで設定できる。

Fee.Audio.Audio.GetInstance().PlaySe(Data.Data.SEID_COMMON,Game.Data.SeCommonType.Cancel);


テクスチャ

「takoyaki1」「takoyaki2」「takoyaki3」はエクセルの"TAKOYAKI1"、"TAKOYAKI2"、"TAKOYAKI3"のパスからロードされている。

//player_texture

UnityEngine.Texture2D t_player_texture = null;
switch(OnMemory.GetInstance().player_index){
case 1:
{
t_player_texture = OnMemory.GetInstance().data.takoyaki1;
}break;
case 2:
{
t_player_texture = OnMemory.GetInstance().data.takoyaki2;
}break;
case 3:
{
t_player_texture = OnMemory.GetInstance().data.takoyaki3;
}break;
}


テキストID


通常

エクセルで指定した文字列を取得。

image.png

//たこ焼きパーティー

string t_text = OnMemory.GetInstance().data.GetText("TEXTID_TITLE_TITLE");


引数指定

実行時に特定のキーワードを数値と差し替える。

image.png

//9999 マヨ

string t_text = OnMemory.GetInstance().data.GetText("TEXTID_GAMEEND_MAYO",9999);


データ更新時間

計算結果を取得。

image.png

//2019/07/07 7:00:26

string t_text = OnMemory.GetInstance().data.GetText("TEXTID_VERSION");


感想

扱ったデータの総量がそれほど多くなかったため大きな恩恵は得られなかったが、特にトラブルもなく実践導入できた。