Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by MoJoe_Blue_ · Jan 17, 2018 at 10:26 PM · editorinspectorassetserializationscriptableobject

[Solved]Why doesn't my ScriptableObject based asset save using a custom inspector ?

So I made an asset system based on the ScriptableObject. I have several assets made this way and they all save perfectly but one. Some have custom inpector display, some have not.


My problem is that I can't identify why this one does not save. Every time I hit the Play button or change scene in Editor the asset is reset to default.
I tried to use EditorUtility.SetDirty(...), AssetDatabase.SaveAssets(), SerializedObject.ApplyModifiedProperties(), none of them have any effect.


Here is the asset that doesn't save :

 using UnityEngine;
 
 [CreateAssetMenu(fileName = "DefaultMap", menuName = "Terrain/Map")]
 public class FightMapData : ObjectData
 {
     [SerializeField]
     private int height = 1;
     public int  Height { get { return height; } set { height = value; } }
     [SerializeField]
     private int width = 1;
     public int  Width { get { return width; } set { width = value; } }
     
     [SerializeField]
     private TileData[][]    terrain;
     public TileData[][]     Terrain { get { return terrain; } set { terrain = value; } }
 
     public void ResizeTerrain()
     {
         if (terrain == null)
             terrain = new TileData[width][];
         else if (terrain.Length == width && terrain[0] != null && terrain[0].Length == height)
             return;
 
         TileData[][] terrainCopy = new TileData[width][];
 
         for (int i = 0; i < width; i++)
         {
             terrainCopy[i] = new TileData[height];
 
             for (int j = 0; j < height; j++)
             {
                 if (terrain.Length > i && terrain[i] != null && terrain[i].Length > j)
                     terrainCopy[i][j] = terrain[i][j];
                 else
                 {
                     Debug.Log("else,      height : " + height);
                     terrainCopy[i][j] = null;
 
                     if (terrain.Length > i)
                     {
                         if (terrain[i] == null)
                             Debug.Log("null");
                         else
                             Debug.Log("terrain[i].length <= j");
                     }
                     else
                         Debug.Log("terrain.length <= i");
                 }
             }
         }
 
         terrain = new TileData[width][];
 
         for (int i = 0; i < width; i++)
         {
             terrain[i] = new TileData[height];
 
             for (int j = 0; j < height; j++)
             {
                 if (terrainCopy[i][j] == null)
                     terrain[i][j] = null;
                 else
                 {
                     terrain[i][j] = CreateInstance<TileData>();
                     terrain[i][j].Copy(terrainCopy[i][j]);
                 }
             }
         }
     }

  

It's custom inspector :

 using UnityEngine;
 using UnityEditor;
 
 [CustomEditor(typeof(FightMapData))]
 public class FightMapDataEditor : Editor
 {
     private bool mapFoldout = true;
     private Vector2 scrollPosition;
 
     public TileData FillTileData = null;
 
     public override void OnInspectorGUI()
     {
         FightMapData fightMapData = (FightMapData)target;
 
         fightMapData.ResizeTerrain();
 
         EditorGUILayout.Space();
         fightMapData.Id = EditorGUILayout.TextField("Id", fightMapData.Id);
         fightMapData.Name = EditorGUILayout.TextField("Name", fightMapData.Name);
 
         EditorGUILayout.Space();
         fightMapData.Height = EditorGUILayout.IntField("Height", fightMapData.Height);
         fightMapData.Width = EditorGUILayout.IntField("Width", fightMapData.Width);
         
         EditorGUILayout.Space();
         mapFoldout = EditorGUILayout.Foldout(mapFoldout, "Map");
         if (mapFoldout)
         {
             EditorGUILayout.Space();
             FillTileData = (TileData)EditorGUILayout.ObjectField("TileData to fill Map", FillTileData, typeof(TileData), false);
             EditorGUILayout.BeginHorizontal();
             if (GUILayout.Button("Fill"))
                 fightMapData.Fill(FillTileData);
             if (GUILayout.Button("Fill blanks"))
                 fightMapData.FillBlanks(FillTileData);
             EditorGUILayout.EndHorizontal();
 
             EditorGUILayout.Space();
             scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, true, true);
             EditorGUILayout.BeginHorizontal();
             for (int i = 0; i < fightMapData.Terrain.Length; i++)
             {
                 EditorGUILayout.BeginVertical();
                 if (fightMapData.Terrain[i] == null)
                 {
                     EditorGUILayout.EndVertical();
                     continue;
                 }
 
                 for (int j = 0; j < fightMapData.Terrain[i].Length; j++)
                     fightMapData.Terrain[i][j] = (TileData)EditorGUILayout.ObjectField(fightMapData.Terrain[i][j], typeof(TileData), false);
                 EditorGUILayout.EndVertical();
             }
             EditorGUILayout.EndHorizontal();
             EditorGUILayout.EndScrollView();
         }
     }
 }



Here is an example asset that save perfectly :

 using UnityEngine;
 
 [CreateAssetMenu(fileName = "DefaultUnit", menuName = "Unit")]
 public class UnitData : ObjectData
 {
     public enum Classes { None, Soldier }
 
     [SerializeField]
     private Classes _class = 0;
     public Classes   Class { get { return _class; } set { _class = value; } }
 
     [SerializeField]
     private int level = 1;
     public int  Level { get { return level; } set { level = value; } }
 
     [SerializeField]
     private int baseHitPoints = 0;
     public int  BaseHitPoints { get { return baseHitPoints; } set { baseHitPoints = value; } }
     [SerializeField]
     private int strength = 0;
     public int  Strength { get { return strength; } set { strength = value; } }
     [SerializeField]
     private int dexterity = 0;
     public int  Dexterity { get { return dexterity; } set { dexterity = value; } }
     [SerializeField]
     private int luck = 0;
     public int  Luck { get { return luck; } set { luck = value; } }
     [SerializeField]
     private int speed = 0;
     public int  Speed { get { return speed; } set { speed = value; } }
 
     [System.Serializable]
     public struct WeaponRank
     {
         public WeaponData.WeaponType Type;
         public WeaponData.Rank Rank;
         public int Experience;
     }
     [SerializeField]
     private WeaponRank[]    weaponRanks = new WeaponRank[6];
     public WeaponRank[] WeaponRanks { get { return weaponRanks; } set { weaponRanks = value; } }
 
     [SerializeField]
     private bool    canMount = false;
     public bool     CanMount { get { return canMount; } set { canMount = value; } }
     [SerializeField]
     private int movement = 0;
     public int  Movement { get { return movement; } set { movement = value; } }
 
     [SerializeField]
     private ArmorData[] armorPieces = new ArmorData[4];
     public ArmorData[]  ArmorPieces { get { return armorPieces; } set { armorPieces = value; } }
     [SerializeField]
     private WeaponData[]    weapons = new WeaponData[4];
     public WeaponData[]     Weapons { get { return weapons; } set { weapons = value; } }
 
     [SerializeField]
     private HorseData   horse = null;
     public HorseData    Horse { get { return horse; } set { horse = value; } }
 
     [ExecuteInEditMode]
     public void Awake()
     {
         WeaponRanks[0].Type = WeaponData.WeaponType.OneHanded;
         WeaponRanks[1].Type = WeaponData.WeaponType.TwoHanded;
         WeaponRanks[2].Type = WeaponData.WeaponType.Polearms;
         WeaponRanks[3].Type = WeaponData.WeaponType.Archery;
         WeaponRanks[4].Type = WeaponData.WeaponType.Crossbow;
         WeaponRanks[5].Type = WeaponData.WeaponType.Throwing;
     }
 }

  

It's custom inspector :

 using UnityEngine;
 using UnityEditor;
 
 [CustomEditor(typeof(UnitData))]
 public class UnitDataEditor : Editor
 {
     private bool weaponsFoldout = true;
     private bool armorsFoldout = true;
 
     private bool weaponRanksFoldout = true;
 
     public override void OnInspectorGUI()
     {
         UnitData data = (UnitData)target;
 
         EditorGUILayout.Space();
         data.Id = EditorGUILayout.TextField("Id", data.Id);
         data.Name = EditorGUILayout.TextField("Name", data.Name);
 
         EditorGUILayout.Space();
         data.Sprite = (Sprite)EditorGUILayout.ObjectField("Sprite", data.Sprite, typeof(Sprite), false);
 
         EditorGUILayout.Space();
         EditorGUILayout.LabelField("Equipment", EditorStyles.boldLabel);
 
         weaponsFoldout = EditorGUILayout.Foldout(weaponsFoldout, "Weapons");
         if (weaponsFoldout)
         {
             data.Weapons[0] = (WeaponData)EditorGUILayout.ObjectField("Equipped Weapon", data.Weapons[0], typeof(WeaponData), false);
             data.Weapons[1] = (WeaponData)EditorGUILayout.ObjectField("Seond Weapon", data.Weapons[1], typeof(WeaponData), false);
             data.Weapons[2] = (WeaponData)EditorGUILayout.ObjectField("Third Weapon", data.Weapons[2], typeof(WeaponData), false);
             data.Weapons[3] = (WeaponData)EditorGUILayout.ObjectField("Fourth Weapon", data.Weapons[3], typeof(WeaponData), false);
         }
 
         EditorGUILayout.Space();
         armorsFoldout = EditorGUILayout.Foldout(armorsFoldout, "Armors");
         if (armorsFoldout)
         {
             data.ArmorPieces[0] = (ArmorData)EditorGUILayout.ObjectField("Head Armor", data.ArmorPieces[0], typeof(ArmorData), false);
             data.ArmorPieces[1] = (ArmorData)EditorGUILayout.ObjectField("Torso Armor", data.ArmorPieces[1], typeof(ArmorData), false);
             data.ArmorPieces[2] = (ArmorData)EditorGUILayout.ObjectField("Gauntlets", data.ArmorPieces[2], typeof(ArmorData), false);
             data.ArmorPieces[3] = (ArmorData)EditorGUILayout.ObjectField("Boots", data.ArmorPieces[3], typeof(ArmorData), false);
         }
 
         EditorGUILayout.Space();
         data.CanMount = EditorGUILayout.Toggle("Can Mount", data.CanMount);
         if (data.CanMount)
         {
             data.Horse = (HorseData)EditorGUILayout.ObjectField("Horse", data.Horse, typeof(HorseData), false);
             if (data.Horse == null)
                 EditorGUILayout.LabelField("Movement Bonus : 0");
             else
                 EditorGUILayout.LabelField("Movement Bonus : " + data.Horse.MovementBonus);
         }
 
         EditorGUILayout.Space();
         EditorGUILayout.LabelField("Statistics", EditorStyles.boldLabel);
 
         data.Class = (UnitData.Classes)EditorGUILayout.EnumPopup("Class", data.Class);
 
         EditorGUILayout.Space();
         data.Level = EditorGUILayout.IntField("Level", data.Level);
 
         EditorGUILayout.Space();
         data.BaseHitPoints = EditorGUILayout.IntField("Base Hit Points", data.BaseHitPoints);
         data.Strength = EditorGUILayout.IntField("Strength", data.Strength);
         data.Dexterity = EditorGUILayout.IntField("Dexterity", data.Dexterity);
         data.Luck = EditorGUILayout.IntField("Luck", data.Luck);
         data.Speed = EditorGUILayout.IntField("Speed", data.Speed);
         data.Movement = EditorGUILayout.IntField("Movement", data.Movement);
 
         int defense = 0;
         int weight = 0;
 
         for (int i = 0; i < 4; i++)
         {
             if (data.ArmorPieces[i] != null)
             {
                 defense += data.ArmorPieces[i].Defense;
                 weight += data.ArmorPieces[i].Weight;
             }
         }
 
         if (data.Weapons[0] != null)
             weight += data.Weapons[0].Weight;
 
         EditorGUILayout.LabelField("Defense : " + defense);
         EditorGUILayout.LabelField("Weight : " + weight);
 
         EditorGUILayout.Space();
         weaponRanksFoldout = EditorGUILayout.Foldout(weaponRanksFoldout, "Weapon Ranks");
         if (weaponRanksFoldout)
         {
             EditorGUILayout.LabelField("One Handed");
             data.WeaponRanks[0].Rank = (WeaponData.Rank)EditorGUILayout.EnumPopup("Rank", data.WeaponRanks[0].Rank);
             data.WeaponRanks[0].Experience = EditorGUILayout.IntField("Experience", data.WeaponRanks[0].Experience);
             EditorGUILayout.Space();
             EditorGUILayout.LabelField("Two Handed");
             data.WeaponRanks[1].Rank = (WeaponData.Rank)EditorGUILayout.EnumPopup("Rank", data.WeaponRanks[1].Rank);
             data.WeaponRanks[1].Experience = EditorGUILayout.IntField("Experience", data.WeaponRanks[1].Experience);
             EditorGUILayout.Space();
             EditorGUILayout.LabelField("Polearms");
             data.WeaponRanks[2].Rank = (WeaponData.Rank)EditorGUILayout.EnumPopup("Rank", data.WeaponRanks[2].Rank);
             data.WeaponRanks[2].Experience = EditorGUILayout.IntField("Experience", data.WeaponRanks[2].Experience);
             EditorGUILayout.Space();
             EditorGUILayout.LabelField("Archery");
             data.WeaponRanks[3].Rank = (WeaponData.Rank)EditorGUILayout.EnumPopup("Rank", data.WeaponRanks[3].Rank);
             data.WeaponRanks[3].Experience = EditorGUILayout.IntField("Experience", data.WeaponRanks[3].Experience);
             EditorGUILayout.Space();
             EditorGUILayout.LabelField("Crossbows");
             data.WeaponRanks[4].Rank = (WeaponData.Rank)EditorGUILayout.EnumPopup("Rank", data.WeaponRanks[4].Rank);
             data.WeaponRanks[4].Experience = EditorGUILayout.IntField("Experience", data.WeaponRanks[4].Experience);
             EditorGUILayout.Space();
             EditorGUILayout.LabelField("Throwing");
             data.WeaponRanks[5].Rank = (WeaponData.Rank)EditorGUILayout.EnumPopup("Rank", data.WeaponRanks[5].Rank);
             data.WeaponRanks[5].Experience = EditorGUILayout.IntField("Experience", data.WeaponRanks[5].Experience);
         }
     }
 }
Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image pako · Jan 16, 2018 at 07:42 PM 0
Share

@$$anonymous$$oJoe_Blue_ if I understand well, it seems that you've solved your own question:

*EDIT : An array of array (like : ScriptableObject[][] array;) can't be serialize. I fixed my issue using a simple array.

if so, could you post the solution as an answer, rather than an "EDIT" inside the question. It will be more helpful for others having the same problem.

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by MoJoe_Blue_ · Jan 17, 2018 at 10:21 PM

An array of array (like : ScriptableObject[][] array;) can't be serialize. I fixed my issue using a simple array.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image edufireheart · Jul 05, 2020 at 09:32 PM 0
Share

I was searching for a while and people were always telling me to use things like EditorUtility.SetDirty or AssetDatabase.SaveAssets. Even if those are valid propositions for the right cases, all I needed was someone telling me that two dimensional arrays within scriptable objects can't be serialized. Then I could stop searching for convoluted solutions and simply use auxiliary one-dimensional arrays for serialization. Thanks

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

102 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Why doesn't my ScriptableObject save using a custom EditorWindow? 3 Answers

How should I serialize data that is also editable in the Inspector? 2 Answers

Saving UnityEngine.Object into ScriptableObject 1 Answer

ScriptableObject : Serialized Polymorphism Classes Can Not be Deserialize with Polymorphism 1 Answer

Dictionary in inspector 4 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges