2022.4.27 9日目 昨日の投稿忘れていたので、再開です。
目標
今回はUnityのScriptableObjectというものを使ってマスタデータを作成していきます。
参考資料
https://moon-bear.com/2021/01/02/use-scriptable-object/
https://ymgsapo.com/2021/03/01/unity-scriptable-object/
https://www.urablog.xyz/entry/2017/03/28/235739
https://hiyotama.hatenablog.com/entry/2019/08/27/110000
どんな場面で使用するものなのか
・共通データの管理
→敵キャラの最大HPなど、共通のデータを持つものに対して使用できる
・シーンをまたぐデータの保持
→シーンをまたぐデータを保持したいときは、「DontDestroyOnLoadしたゲームオブジェクトに値を持たせる」方法が見受けられるそうです。
一方で、このような場合にはScriptableObjectを使うと便利です。理由は、
・ScriptableObjectはどのシーンからでも参照することができる
(ゲームオブジェクトのようにシーンに依存しない)
・ScriptableObjectはあらかじめインスペクターに登録することができる(シリアライズが可能)
・イベントの管理
実践
では実際にUnityでScriptableObjectを使用していきます。
assetファイルの作成
どのようなデータを持たせるのかを記載したスクリプトを書いていきます。
//ScriptableObject作成
using System;
//ScriptableObject作成
[CreateAssetMenu( fileName = "MissionInfo")]
public class ScriptableTest: ScriptableObject {
public List<Mission> missionList = new List<Mission>();
}
[Serializable]
public class Mission {
//ミッションID
public int id;
//次のミッション
public int nextMissionId;
//ミッション内容
public string missionDetail;
}
ここからはスクリプトの説明です。
[CreateAssetMenu( fileName = "MissionInfo")]
スクリプトの説明後にある、Projectを右クリック~ の動作を実現できるのがこの一文らしいです。この一文を追加することで右クリック>Create にスクリプト名(このタブ名は変更可能、とのこと!)が追加され、assetファイルを作成することができるそうです。
public class ScriptableTest: ScriptableObject {
次に、「ScriptableObject」を継承します。
(要は使えるようにします。(私の解釈で申し訳ありません><。)
[Serializable]
public class Mission {
参考にさせていただいたサイトに、[Serializable]とあり、なんぞやと思ったので調べてみると、「ここでのシリアライズは「直列化」と訳され、メインメモリ上に存在しているオブジェクトなどのデータを文字列やバイト列に変換することを指します。これには、ファイルとして保存したり、ネットワークで送受信したりできるようになるというメリットがあります。
逆に、シリアライズされたデータをもとの状態に復元することをデシリアライズと言います。」 だそうです。
クラスの中は、含めたいデータを変数として宣言しておきます!
説明は以上です。
スクリプトを作成したら、Projectを右クリック>Create>作成したスクリプト名 と選択していきます。
これでScriptableObjectの作成はできたかと思います。
別のスクリプト上での呼び出し方
方法はいくつかあるそうですが一番オーソドックスな方法で行きます。
単純にSerializeFieldでInspecterにアタッチして使用する方法です。
[SerializeField] private ScriptableTest m_infomation = null;
(ただアタッチして使用するのは、色々な場所で参照することになると大変そうですね…)
実際に呼び出してみた↓
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MasterDataController: MonoBehaviour {
[SerializeField] private ScriptableTest m_infomation = null;
// Start is called before the first frame update
void Start() {
foreach( var mission in m_infomation.missionList ) {
Debug.Log( "ID:" + mission.id + " " + "mission:" + mission.missionDetail + " " + "NextMissionID:" + mission.nextMissionId );
}
}
// Update is called once per frame
void Update() {
}
}
となりました。かなり簡単に呼び出しができました。
Excelからデータの読み込み
まずはExcelからデータを読み込んでみます。
今回はNPOIを使用していきます。
準備
NPOIのインポートをしていきます。
ダウンロードすると、拡張子が「.nupkg」となっていると思います。そのままだと解凍できないので、「.zip」とすると解凍できるようになります)
(解凍したフォルダ内lib/net45内のもの全て)
(解凍したフォルダ内lib/net40内のもの全て)
(解凍したフォルダ内lib/net45内のもの全て)
入れると以下のようになっているはずです。
(今回はAsset下にEditer/npoiフォルダを作成して、そこにインポートしています)
これで準備完了です。
Excelデータの読み込み
こちらを参考にさせていただきました。
using System.IO;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.HSSF.Util;
using NPOI.SS.Util;
using UnityEngine;
public class ExcelToScriptableObject: MonoBehaviour {
// Start is called before the first frame update
void Start() {
if( !File.Exists( @"C:\StudyUnity\ScriptableObjectStudy\Assets\Script\MissionMasterData.xls" ) ) {
return;
}
//Excelブックを開く
IWorkbook book = WorkbookFactory.Create( @"C:\StudyUnity\ScriptableObjectStudy\Assets\Script\MissionMasterData.xls" );
CellReference reference = new CellReference( "B5" );
IRow row = book.GetSheetAt( 0 ).GetRow( reference.Col );
ICell cell = row.GetCell( reference.Col );
var str = cell.StringCellValue;
Debug.Log( str );
}
まずは試しに↑のようなコードを書いてみました。(読み込みのみしてみました)A1形式で読み込みをしております。
以下コードの説明です。
using System.IO;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.HSSF.Util;
using NPOI.SS.Util;
using UnityEngine;
必要なusingディレクティブを追加します。
if( !File.Exists( @"C:\StudyUnity\ScriptableObjectStudy\Assets\Script\MissionMasterData.xls" ) ) {
return;
}
ここで読み込むExcelデータがあるかどうかを検索して、無ければ関数を抜ける処理をしています。(必要ないとは思いますが念のためかいてあります)
IWorkbook book = WorkbookFactory.Create( @"C:\StudyUnity\ScriptableObjectStudy\Assets\Script\MissionMasterData.xls" );
読み込むExcelデータを開きます。
CellReference reference = new CellReference( "B5" );
A1形式で読み込むセルを指定します。
IRow row = book.GetSheetAt( 0 ).GetRow( reference.Col );
ICell cell = row.GetCell( reference.Col );
book.GetSheetAt( 0 )→どのシートを指定するか
GetRow( reference.Col )→どのセルか
ICell cell = row.GetCell( reference.Col );→セルの情報を読み込み
var str = cell.StringCellValue;
cell.StringCellValue 今回はStringを読み込んだのでこのように書きましたが、どのような値を読み込むかで変わってくるようです。
これを実行すると以下のようになります。(MasterDataに使用するExcelによって変わります)
明日は続きをやっていきます。