RPGを作る課題の時に勝手に作成した副産物を紹介します。
ソースコードかなり汚いから次作る時は直したいところ
[CreateAssetMenu(fileName = "Data", menuName = "EnemyData")] public class EnemyDatas : ScriptableObject { //課題中List使用禁止だったからListのが扱いやすいかも [SerializeField, HideInInspector] private EnemyData[] enemydatas_; public EnemyData[] GetEnemyDatas{ get{ return enemydatas_; } } public void InitData() { Debug.Log("InitData"); enemydatas_ = new EnemyData[1]; enemydatas_[0] = new EnemyData(); } public void AddData() { EnemyData[] tmpDatas = new EnemyData[enemydatas_.Length + 1]; for (int i = 0; i < enemydatas_.Length; i++) { tmpDatas[i] = enemydatas_[i]; } tmpDatas[tmpDatas.Length - 1] = new EnemyData(); enemydatas_ = tmpDatas; } public void RemoveData() { if (enemydatas_.Length==0) { return; } EnemyData[] tmpDatas = new EnemyData[enemydatas_.Length - 1]; for (int i = 0; i < tmpDatas.Length; i++) { tmpDatas[i] = enemydatas_[i]; } enemydatas_ = tmpDatas; } } [System.Serializable] public struct EnemyData { //publicで横着しない.. public Sprite sprite_; public string name_; public int level_; public int hp_; public int mp_; public int attack_power_; public int magic_power_; public ActionType actiontype_; public HaveMagicType havemagictype_; public enum ActionType { ATTACK=1<<0, MAGIC=1<<1, UNIQUE_1=1<<2, UNIQUE_2=1<<3, UNIQUE_3=1<<4, } public enum HaveMagicType { DAMGAE=1<<0, AFFECT=1<<1, } }
using UnityEditor; public class EditEnemyDatas : EditorWindow { private EnemyDatas edit_enemydatas_; public EnemyDatas GetEditEnemyDatas { get { return edit_enemydatas_; } } public void SetEditEnemyDatas(EnemyDatas enemydatas) { edit_enemydatas_ = enemydatas; } [MenuItem("Tools/EditEnemyDatas")] public static void Open() { EditEnemyDatas editenemydatas = GetWindow<EditEnemyDatas>(); var path = "Assets/EnemyDatas.asset"; editenemydatas.SetEditEnemyDatas(AssetDatabase.LoadAssetAtPath<EnemyDatas>(path)); if (editenemydatas.GetEditEnemyDatas == null) { editenemydatas.SetEditEnemyDatas(ScriptableObject.CreateInstance<EnemyDatas>()); AssetDatabase.CreateAsset(editenemydatas.GetEditEnemyDatas, path); } if (editenemydatas.edit_enemydatas_.GetEnemyDatas == null) { editenemydatas.edit_enemydatas_.InitData(); } } public void OnDisable() { EditorUtility.SetDirty(edit_enemydatas_); AssetDatabase.SaveAssets(); Debug.Log("Close"); } private void OnGUI() { var value_layout_width = GUILayout.Width(70); var value_layout_height = GUILayout.Height(20); var sprite_layout_width = GUILayout.Width(40); var sprite_layout_height = GUILayout.Height(40); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("画像", sprite_layout_width, value_layout_height); EditorGUILayout.LabelField("名前", value_layout_width, value_layout_height); EditorGUILayout.LabelField("レベル", value_layout_width, value_layout_height); EditorGUILayout.LabelField("HP", value_layout_width, value_layout_height); EditorGUILayout.LabelField("MP", value_layout_width, value_layout_height); EditorGUILayout.LabelField("攻撃力", value_layout_width, value_layout_height); EditorGUILayout.LabelField("魔法攻撃力", value_layout_width, value_layout_height); EditorGUILayout.LabelField("行動", value_layout_width, value_layout_height); EditorGUILayout.LabelField("使用魔法", value_layout_width, value_layout_height); EditorGUILayout.EndHorizontal(); for (int i = 0; i < edit_enemydatas_.GetEnemyDatas.Length; i++) { EnemyData enemyData = edit_enemydatas_.GetEnemyDatas[i]; EditorGUILayout.BeginVertical("Box");//横------------------------------------- EditorGUILayout.BeginHorizontal(); enemyData.sprite_ = (Sprite)EditorGUILayout.ObjectField(enemyData.sprite_, typeof(Sprite), false, sprite_layout_width, sprite_layout_height); enemyData.name_ = EditorGUILayout.TextField(enemyData.name_, value_layout_width, value_layout_height); enemyData.level_ = EditorGUILayout.IntField(enemyData.level_, value_layout_width, value_layout_height); enemyData.hp_ = EditorGUILayout.IntField(enemyData.hp_, value_layout_width, value_layout_height); enemyData.mp_ = EditorGUILayout.IntField(enemyData.mp_, value_layout_width, value_layout_height); enemyData.attack_power_ = EditorGUILayout.IntField(enemyData.attack_power_, value_layout_width, value_layout_height); enemyData.magic_power_ = EditorGUILayout.IntField(enemyData.magic_power_, value_layout_width, value_layout_height); enemyData.actiontype_ = (EnemyData.ActionType)EditorGUILayout.EnumFlagsField(enemyData.actiontype_, value_layout_width, value_layout_height); enemyData.havemagictype_ = (EnemyData.HaveMagicType)EditorGUILayout.EnumFlagsField(enemyData.havemagictype_, value_layout_width, value_layout_height); EditorGUILayout.EndHorizontal();//横-------------------------------------- EditorGUILayout.EndVertical(); edit_enemydatas_.GetEnemyDatas[i] = enemyData; } if (GUILayout.Button("データ追加")) { edit_enemydatas_.AddData(); } if (GUILayout.Button("データ削除")) { edit_enemydatas_.RemoveData(); } if (EditorGUI.EndChangeCheck()) { UnityEditor.Undo.RecordObject(edit_enemydatas_, "Edit ExampleEditorWindow"); EditorUtility.SetDirty(edit_enemydatas_); } } }
難しいことは何もしてないですが応用できそうなので残しておきます。
どちらかと言えばこっからが本題
作成したデータが初期化される場合
ScriptableObjectのデータがコンパイル時や再起動時に初期化される現象がおきました
対処としてこちらの記事を参考にしました
tsubakit1.hateblo.jp
私の場合はシリアル化していないのが原因で、EnemyData構造体はシリアライズしてたけどScriptableObjectを継承したEnemyDatasのメンバをprivateで宣言していたためシリアル化されず初期化されてしまいました。
シリアル化についてはこちらを参照しました。
docs.unity3d.com
また、調べている時に別の理由で初期化される場合の記事を見つけたのでリンクしておきます。
kan-kikuchi.hatenablog.com