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 jakejolli · Nov 14, 2017 at 03:27 PM · c#editorcustom-inspector

Custom Inspector's Values Reset in Play Mode, But Only Sometimes

I've written my first custom inspector for my game's Stats classes.

I have a base Stats class, then subclasses EnemyStats and PlayerStats. I have a custom inspector for both subclasses and they're both pretty much identical. However, my PlayerStats values always reset when I enter play mode, but my EnemyStats values persist.

Why is this happening?

PlayerStatsEditor:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEditor;
 
 /*
  * Creates a custom inspector for PlayerStats.
  * Allows stats to be updated and for their related stats to automatically update accordingly.
  * Also grants the ability to restore either health or mana at run time with the click of a button.
  * */
 
 //TODO: Experience Bar and levelling -- Add a level up button.
 //Show status effects, add a clear status effects button. -- Maybe status effects should be shown in a custom SpellManager inspector?
 
 [CustomEditor(typeof(PlayerStats))]
 public class PlayerStatsEditor : Editor {
 
     PlayerStats playerStats;
 
     public override void OnInspectorGUI() {        
         playerStats = (PlayerStats)target;
 
         DrawHeading("Primary/Governing Stats");
         DrawStatHeadings();
         playerStats.BaseStrength = DrawStat(playerStats.BaseStrength, "STR", Stat.Strength);
         playerStats.BaseEndurance = DrawStat(playerStats.BaseEndurance, "END", Stat.Endurance);
         playerStats.BaseAgility = DrawStat(playerStats.BaseAgility, "AGI", Stat.Agility);
         playerStats.BaseIntelligence = DrawStat(playerStats.BaseIntelligence, "INT", Stat.Intelligence);
         playerStats.BaseLuck = DrawStat(playerStats.BaseLuck, "LCK", Stat.Luck);
         playerStats.BaseCharisma = DrawStat(playerStats.BaseCharisma, "CHA", Stat.Charisma);
 
         EditorGUILayout.Space();
         EditorGUILayout.Space();
 
         DrawHeading("Secondary Stats");
         DrawStatHeadings();
         playerStats.BaseMaxHealth = DrawStat(playerStats.BaseMaxHealth, "MaxHP", Stat.MaxHealth);
         playerStats.CurrentHealth = DrawFilledBar(playerStats.CurrentHealth, Stat.MaxHealth, Color.red);
         if (GUILayout.Button("Restore Health", GUILayout.Width(Screen.width - 40f))) {
             playerStats.CurrentHealth = playerStats.GetCalculatedStat(Stat.MaxHealth);
         }
         playerStats.BaseMaxMana = DrawStat(playerStats.BaseMaxMana, "MaxMP", Stat.MaxMana);
         playerStats.CurrentMana = DrawFilledBar(playerStats.CurrentMana, Stat.MaxMana, Color.cyan);
         if (GUILayout.Button("Restore Mana", GUILayout.Width(Screen.width - 40f))) {
             playerStats.CurrentMana = playerStats.GetCalculatedStat(Stat.MaxMana);            
         }        
 
         EditorGUILayout.Space();
         EditorGUILayout.Space();
         playerStats.BaseXPModifier = DrawStat(playerStats.BaseXPModifier, "XPMod", Stat.XPModifier);
         playerStats.BaseDamage = DrawStat(playerStats.BaseDamage, "Damage", Stat.Damage);
         playerStats.BaseDefense = DrawStat(playerStats.BaseDefense, "Defense", Stat.Defense);
         playerStats.BaseToHit = DrawStat(playerStats.BaseToHit, "ToHit", Stat.ToHit);
         playerStats.BaseDodge = DrawStat(playerStats.BaseDodge, "Dodge", Stat.Dodge);
         playerStats.BaseSpeed = DrawStat(playerStats.BaseSpeed, "Speed", Stat.Speed);
         playerStats.BaseCarryingCapacity = DrawStat(playerStats.BaseCarryingCapacity, "Weight Cap.", Stat.CarryingCapacity);
         playerStats.BaseBarter = DrawStat(playerStats.BaseBarter, "Barter", Stat.Barter);
 
         EditorGUILayout.Space();
         EditorGUILayout.Space();
         DrawHeading("Tertiary/Magick");
         DrawStatHeadings();
         playerStats.BaseEarth = DrawStat(playerStats.BaseEarth, "Earth", Stat.Earth);
         playerStats.BaseEarthDef = DrawStat(playerStats.BaseEarthDef, "Earth Def.", Stat.EarthDef);
 
         playerStats.BaseFire = DrawStat(playerStats.BaseFire, "Fire", Stat.Fire);
         playerStats.BaseFireDef = DrawStat(playerStats.BaseFireDef, "Fire Def.", Stat.FireDef);
 
         playerStats.BaseWind = DrawStat(playerStats.BaseWind, "Wind", Stat.Wind);
         playerStats.BaseWindDef = DrawStat(playerStats.BaseWindDef, "Wind Def.", Stat.WindDef);
 
         playerStats.BaseWater = DrawStat(playerStats.BaseWater, "Water", Stat.Water);
         playerStats.BaseWaterDef = DrawStat(playerStats.BaseWaterDef, "Water Def.", Stat.WaterDef);
 
         playerStats.BaseLightning = DrawStat(playerStats.BaseLightning, "Lightning", Stat.Lightning);
         playerStats.BaseLightningDef = DrawStat(playerStats.BaseLightningDef, "Lightning Def.", Stat.LightningDef);
 
         playerStats.BaseHealing = DrawStat(playerStats.BaseHealing, "Healing", Stat.Healing);
 
         playerStats.BaseDeath = DrawStat(playerStats.BaseDeath, "Death", Stat.Death);
         playerStats.BaseDeathDef = DrawStat(playerStats.BaseDeathDef, "Death Def.", Stat.DeathDef);
 
         playerStats.BaseBlood = DrawStat(playerStats.BaseBlood, "Blood", Stat.Blood);
         playerStats.BaseBloodDef = DrawStat(playerStats.BaseBloodDef, "Blood Def.", Stat.BloodDef);
 
         playerStats.BaseBattle = DrawStat(playerStats.BaseBattle, "Battle", Stat.Battle);
         playerStats.BaseBattleDef = DrawStat(playerStats.BaseBattleDef, "Battle Def.", Stat.BattleDef);
 
         playerStats.BaseAlteration = DrawStat(playerStats.BaseAlteration, "Alteration", Stat.Alteration);
         playerStats.BaseAlterationDef = DrawStat(playerStats.BaseAlterationDef, "Alteration Def.", Stat.AlterationDef);
 
         EditorGUILayout.Space();
         EditorGUILayout.Space();
         DrawHeading("Tertiary/Weapons & Armor");
         DrawStatHeadings();
         playerStats.BaseLightArmor = DrawStat(playerStats.BaseLightArmor, "LightArmor", Stat.LightArmor);
         playerStats.BaseHeavyArmor = DrawStat(playerStats.BaseHeavyArmor, "HeavyArmor", Stat.HeavyArmor);
         playerStats.BaseRangedWeapons = DrawStat(playerStats.BaseRangedWeapons, "RangedWeapons", Stat.RangedWeapons);
         playerStats.BaseLightWeapons = DrawStat(playerStats.BaseLightWeapons, "LightWeapons", Stat.LightWeapons);
         playerStats.BaseHeavyWeapons = DrawStat(playerStats.BaseHeavyWeapons, "HeavyWeapons", Stat.HeavyWeapons);
        
         playerStats.CalculateSecondaryStats();
         serializedObject.Update();
         serializedObject.ApplyModifiedProperties();
     }
 
     private float DrawFilledBar(float statValue, Stat stat, Color fillColor) {
 
         float lineOffset = 18;
 
         EditorGUI.DrawRect(new Rect(20, GUILayoutUtility.GetLastRect().position.y + lineOffset, Screen.width - 40, 16), Color.gray);
         EditorGUI.DrawRect(new Rect(21, GUILayoutUtility.GetLastRect().position.y + lineOffset + 1, Screen.width * (statValue / playerStats.GetCalculatedStat(stat)) - (41 * (statValue / playerStats.GetCalculatedStat(stat))), 14), fillColor);
 
         EditorGUILayout.BeginHorizontal();
         EditorGUILayout.LabelField("", EditorStyles.boldLabel, GUILayout.Width(Screen.width * .4f - 30f));
         statValue = EditorGUILayout.FloatField(statValue, GUILayout.Width(30));
         EditorGUILayout.LabelField(" / " + playerStats.GetCalculatedStat(stat).ToString() + " (" + statValue / playerStats.GetCalculatedStat(stat) * 100 + "%)", EditorStyles.boldLabel, GUILayout.Width(Screen.width * .6f));
         EditorGUILayout.EndHorizontal();
 
         return statValue;
     }
 
     private static void DrawHeading(string heading) {
         int originalFontSize = EditorStyles.boldLabel.fontSize;
         EditorStyles.boldLabel.fontSize = 14;
         EditorGUILayout.LabelField(heading, EditorStyles.boldLabel, GUILayout.Height(20f));
         EditorStyles.boldLabel.fontSize = originalFontSize;
     }
 
     private static void DrawStatHeadings() {
         float maxWidth = Screen.width / 6 - 20f;
         EditorGUILayout.BeginHorizontal();
         EditorGUILayout.LabelField("Stat", EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
         EditorGUILayout.LabelField("Base", EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
         EditorGUILayout.LabelField("Buff", EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
         EditorGUILayout.LabelField("Equipment", EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
         EditorGUILayout.LabelField("Bonus", EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
         EditorGUILayout.LabelField("Calculated", EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
         EditorGUILayout.EndHorizontal();
     }
 
     private float DrawStat(float statValue, string label, Stat stat) {
         float maxWidth = Screen.width / 6 - 20f;
         string statString = stat.ToString();
 
         EditorGUILayout.BeginHorizontal();
         EditorGUILayout.LabelField(label, EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
         statValue = EditorGUILayout.FloatField(statValue, GUILayout.MaxWidth(maxWidth));
         EditorGUILayout.LabelField(playerStats.BuffStats[statString].ToString(), GUILayout.MaxWidth(maxWidth));
         EditorGUILayout.LabelField(playerStats.EquipmentStats[statString].ToString(), GUILayout.MaxWidth(maxWidth));
         playerStats.BonusStats[statString] = EditorGUILayout.FloatField(playerStats.BonusStats[statString], GUILayout.MaxWidth(maxWidth));
         EditorGUILayout.LabelField(playerStats.GetCalculatedStat(stat).ToString(), GUILayout.MaxWidth(maxWidth));
         EditorGUILayout.EndHorizontal();
 
         return statValue;
     }
 }
 

EnemyStatsEditor:

  using System.Collections;
     using System.Collections.Generic;
     using UnityEngine;
     using UnityEditor;
     
     /*
      * Creates a custom inspector for EnemyStats.
      * Allows stats to be updated and for their related stats to automatically update accordingly.
      * Also grants the ability to restore either health or mana at run time with the click of a button.
      * */
     
     //TODO: Experience Bar and levelling -- Add a level up button.
     //Show status effects, add a clear status effects button. -- Maybe status effects should be shown in a custom SpellManager inspector?
     
     [CustomEditor(typeof(EnemyStats))]
     public class EnemyStatsEditor : Editor {
     
         EnemyStats enemyStats;
     
         public override void OnInspectorGUI() {
             enemyStats = (EnemyStats)target;
     
             DrawHeading("Primary/Governing Stats");
             DrawStatHeadings();
             enemyStats.BaseStrength = DrawStat(enemyStats.BaseStrength, "STR", Stat.Strength);
             enemyStats.BaseEndurance = DrawStat(enemyStats.BaseEndurance, "END", Stat.Endurance);
             enemyStats.BaseAgility = DrawStat(enemyStats.BaseAgility, "AGI", Stat.Agility);
             enemyStats.BaseIntelligence = DrawStat(enemyStats.BaseIntelligence, "INT", Stat.Intelligence);
             enemyStats.BaseLuck = DrawStat(enemyStats.BaseLuck, "LCK", Stat.Luck);
     
             EditorGUILayout.Space();
             EditorGUILayout.Space();
     
             DrawHeading("Secondary Stats");
             DrawStatHeadings();
             enemyStats.BaseMaxHealth = DrawStat(enemyStats.BaseMaxHealth, "MaxHP", Stat.MaxHealth);
             enemyStats.CurrentHealth = DrawFilledBar(enemyStats.CurrentHealth, Stat.MaxHealth, Color.red);
             if (GUILayout.Button("Restore Health", GUILayout.Width(Screen.width - 40f))) {
                 enemyStats.CurrentHealth = enemyStats.GetCalculatedStat(Stat.MaxHealth);
             }
             enemyStats.BaseMaxMana = DrawStat(enemyStats.BaseMaxMana, "MaxMP", Stat.MaxMana);
             enemyStats.CurrentMana = DrawFilledBar(enemyStats.CurrentMana, Stat.MaxMana, Color.cyan);
             if (GUILayout.Button("Restore Mana", GUILayout.Width(Screen.width - 40f))) {
                 enemyStats.CurrentMana = enemyStats.GetCalculatedStat(Stat.MaxMana);
             }
     
             EditorGUILayout.Space();
             EditorGUILayout.Space();
             enemyStats.BaseDamage = DrawStat(enemyStats.BaseDamage, "Damage", Stat.Damage);
             enemyStats.BaseDefense = DrawStat(enemyStats.BaseDefense, "Defense", Stat.Defense);
             enemyStats.BaseToHit = DrawStat(enemyStats.BaseToHit, "ToHit", Stat.ToHit);
             enemyStats.BaseDodge = DrawStat(enemyStats.BaseDodge, "Dodge", Stat.Dodge);
             enemyStats.BaseSpeed = DrawStat(enemyStats.BaseSpeed, "Speed", Stat.Speed);
     
             EditorGUILayout.Space();
             EditorGUILayout.Space();
             DrawHeading("Tertiary/Magick");
             DrawStatHeadings();
             enemyStats.BaseEarth = DrawStat(enemyStats.BaseEarth, "Earth", Stat.Earth);
             enemyStats.BaseEarthDef = DrawStat(enemyStats.BaseEarthDef, "Earth Def.", Stat.EarthDef);
     
             enemyStats.BaseFire = DrawStat(enemyStats.BaseFire, "Fire", Stat.Fire);
             enemyStats.BaseFireDef = DrawStat(enemyStats.BaseFireDef, "Fire Def.", Stat.FireDef);
     
             enemyStats.BaseWind = DrawStat(enemyStats.BaseWind, "Wind", Stat.Wind);
             enemyStats.BaseWindDef = DrawStat(enemyStats.BaseWindDef, "Wind Def.", Stat.WindDef);
     
             enemyStats.BaseWater = DrawStat(enemyStats.BaseWater, "Water", Stat.Water);
             enemyStats.BaseWaterDef = DrawStat(enemyStats.BaseWaterDef, "Water Def.", Stat.WaterDef);
     
             enemyStats.BaseLightning = DrawStat(enemyStats.BaseLightning, "Lightning", Stat.Lightning);
             enemyStats.BaseLightningDef = DrawStat(enemyStats.BaseLightningDef, "Lightning Def.", Stat.LightningDef);
     
             enemyStats.BaseHealing = DrawStat(enemyStats.BaseHealing, "Healing", Stat.Healing);
     
             enemyStats.BaseDeath = DrawStat(enemyStats.BaseDeath, "Death", Stat.Death);
             enemyStats.BaseDeathDef = DrawStat(enemyStats.BaseDeathDef, "Death Def.", Stat.DeathDef);
     
             enemyStats.BaseBlood = DrawStat(enemyStats.BaseBlood, "Blood", Stat.Blood);
             enemyStats.BaseBloodDef = DrawStat(enemyStats.BaseBloodDef, "Blood Def.", Stat.BloodDef);
     
             enemyStats.BaseBattle = DrawStat(enemyStats.BaseBattle, "Battle", Stat.Battle);
             enemyStats.BaseBattleDef = DrawStat(enemyStats.BaseBattleDef, "Battle Def.", Stat.BattleDef);
     
             enemyStats.BaseAlteration = DrawStat(enemyStats.BaseAlteration, "Alteration", Stat.Alteration);
             enemyStats.BaseAlterationDef = DrawStat(enemyStats.BaseAlterationDef, "Alteration Def.", Stat.AlterationDef);
     
             EditorGUILayout.Space();
             EditorGUILayout.Space();
             DrawHeading("Tertiary/Weapons & Armor");
             DrawStatHeadings();
             enemyStats.BaseLightArmor = DrawStat(enemyStats.BaseLightArmor, "LightArmor", Stat.LightArmor);
             enemyStats.BaseHeavyArmor = DrawStat(enemyStats.BaseHeavyArmor, "HeavyArmor", Stat.HeavyArmor);
             enemyStats.BaseRangedWeapons = DrawStat(enemyStats.BaseRangedWeapons, "RangedWeapons", Stat.RangedWeapons);
             enemyStats.BaseLightWeapons = DrawStat(enemyStats.BaseLightWeapons, "LightWeapons", Stat.LightWeapons);
             enemyStats.BaseHeavyWeapons = DrawStat(enemyStats.BaseHeavyWeapons, "HeavyWeapons", Stat.HeavyWeapons);
     
     
             enemyStats.CalculateSecondaryStats();
             serializedObject.ApplyModifiedProperties();
         }
     
         private float DrawFilledBar(float statValue, Stat stat, Color fillColor) {
     
             float lineOffset = 18;
     
             EditorGUI.DrawRect(new Rect(20, GUILayoutUtility.GetLastRect().position.y + lineOffset, Screen.width - 40, 16), Color.gray);
             EditorGUI.DrawRect(new Rect(21, GUILayoutUtility.GetLastRect().position.y + lineOffset + 1, Screen.width * (statValue / enemyStats.GetCalculatedStat(stat)) - (41 * (statValue / enemyStats.GetCalculatedStat(stat))), 14), fillColor);
     
             EditorGUILayout.BeginHorizontal();
             EditorGUILayout.LabelField("", EditorStyles.boldLabel, GUILayout.Width(Screen.width * .4f - 30f));
             statValue = EditorGUILayout.FloatField(statValue, GUILayout.Width(30));
             EditorGUILayout.LabelField(" / " + enemyStats.GetCalculatedStat(stat).ToString() + " (" + statValue / enemyStats.GetCalculatedStat(stat) * 100 + "%)", EditorStyles.boldLabel, GUILayout.Width(Screen.width * .6f));
             EditorGUILayout.EndHorizontal();
     
             return statValue;
         }
     
         private static void DrawHeading(string heading) {
             int originalFontSize = EditorStyles.boldLabel.fontSize;
             EditorStyles.boldLabel.fontSize = 14;
             EditorGUILayout.LabelField(heading, EditorStyles.boldLabel, GUILayout.Height(20f));
             EditorStyles.boldLabel.fontSize = originalFontSize;
         }
     
         private static void DrawStatHeadings() {
             float maxWidth = Screen.width / 6 - 20f;
             EditorGUILayout.BeginHorizontal();
             EditorGUILayout.LabelField("Stat", EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
             EditorGUILayout.LabelField("Base", EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
             EditorGUILayout.LabelField("Buff", EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
             EditorGUILayout.LabelField("Equipment", EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
             EditorGUILayout.LabelField("Bonus", EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
             EditorGUILayout.LabelField("Calculated", EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
             EditorGUILayout.EndHorizontal();
         }
     
         private float DrawStat(float statValue, string label, Stat stat) {
             float maxWidth = Screen.width / 6 - 20f;
             string statString = stat.ToString();
     
             EditorGUILayout.BeginHorizontal();
             EditorGUILayout.LabelField(label, EditorStyles.boldLabel, GUILayout.MaxWidth(maxWidth));
             statValue = EditorGUILayout.FloatField(statValue, GUILayout.MaxWidth(maxWidth));
             EditorGUILayout.LabelField(enemyStats.BuffStats[statString].ToString(), GUILayout.MaxWidth(maxWidth));
             EditorGUILayout.LabelField(enemyStats.EquipmentStats[statString].ToString(), GUILayout.MaxWidth(maxWidth));
             enemyStats.BonusStats[statString] = EditorGUILayout.FloatField(enemyStats.BonusStats[statString], GUILayout.MaxWidth(maxWidth));
             EditorGUILayout.LabelField(enemyStats.GetCalculatedStat(stat).ToString(), GUILayout.MaxWidth(maxWidth));
             EditorGUILayout.EndHorizontal();
     
             return statValue;
         }
     }
     





Comment
Add comment
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

2 Replies

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

Answer by Bunny83 · Nov 14, 2017 at 04:40 PM

You have several problems in your code. First and formost you should not mix SerializedObject / SerializedProperties with the "target" variable. Those a two very different approaches to the same thing.


Second you don't seem to understand how SerializedObject should be used or how it works. Also you don't properly "communicate" your changes to Unity's serialization system.


As i said there are two ways to edit the serialized data of an object.

SerializedObject / SerializedProperty

The SerializedObject is the preferred way of manipulating the serialized data. It supports multi object editing out of the box and does handle undo registration automatically.


The SerializedObject is actually a "copy" of the serialized data. Note that the serialized data is completely abstracted from the actual classes and instances. It's just the plain data. When you call Update on the SerializedObject it will pull the current data from disk into the SerializedObject / SerializedProperties. Now you could change / edit / modify the various SerializedProperties. This is done be reading / writing one of the following values:


  • animationCurveValue

  • arraySize

  • boolValue

  • boundsIntValue

  • boundsValue

  • colorValue

  • doubleValue

  • enumValueIndex

  • exposedReferenceValue

  • floatValue

  • intValue

  • longValue

  • objectReferenceValue

  • quaternionValue

  • rectIntValue

  • rectValue

  • stringValue

  • vector2IntValue

  • vector2Value

  • vector3IntValue

  • vector3Value

  • vector4Value


You can either bring up your own UI for each property by using FindProperty or by iterating through all properties and use a PropertyField. A SerializedProperty is actually an "iterator object". That means you can simply call Next on it and the serializedProperty will represent the next serialized value as they would appear in the normal inspector. If you roll your own UI you may want to check the propertyType. Keep in mind that you have to use the "correct" value from the above mentioned list. So you can't read / write "stringValue" from a SerializedProperty that actually represents a Vector3 value. PropertyField handles all those types automatically. Also PropertyField will use any PropertyDrawers that might be declared for this field / fieldtype.


After you modified any of those "properties" you have to call "ApplyModifiedProperties" on the SerializedObject to actually apply all the changes to the underlying serialized data on disk.


target / targets

Another way to edit the serialized data is to directly access the target class instance / instances. Unlike the SerializedObject here you have to handle multi object editing yourself. So when more than one object is selected you would need to use targets instead. Note that multi object editing is only possible when your Editor has the CanEditMultipleObjects attribute.


Using target is actually the legacy method of editing objects but it can still be used. However you have to manually tell Unity that you edit this object. Since we now talk about "normal" class instances Unity doesn't know when you modified something. To do this you would need to use the Undo class. You usually have to call Undo.RecordObject before you do any changes to the object. This method registers the given object to be checked / serialized after the editor has finished the current execution.


Note that when you mix SerializedObject and target access you can get undefined results. When you call ApplyModifiedProperties you most likely erase all changes you've done manually


Keep in mind that Unity can only "truly" serialize classes which are derived from UnityEngine.Object. Custom "Serialized" classes are not serialized on their own but are simple "sub data" of the UnityEngine.Object derived type that references this class.


I highly recommend to read the Script Serialization documentation carefully.

Comment
Add comment · Show 2 · 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 Bunny83 · Nov 14, 2017 at 04:50 PM 0
Share

Ps: In many cases implementing a PropertyDrawer is usually easier when you only want to change how certain serialized values are displayed. In addition you can use DecoratorDrawers to split the different values into sections or add a header text. Unity has some built-in decorators (Tooltip, Header, Space, ...) and even PropertyDrawers (Range, TextArea, Delayed, ...) for some special cases.

avatar image jakejolli Bunny83 · Nov 17, 2017 at 02:00 PM 0
Share

I was hoping for a quick and easy answer, but alas, it looks like I have some learning to do. Thanks for the detailed response!

avatar image
0

Answer by Tourist · Nov 14, 2017 at 04:11 PM

You call for serializedObject.Update just before applying modified properties.

serializedObject.Update() must be at the beginning of your OnInspectorGUI because it may reset modified values.

Comment
Add comment · 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

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

421 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 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 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 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 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

Unity Custom Editor Texture Warning 2 Answers

editorguilayout.objectfield issue 1 Answer

How to change inspector with non-Monobehaviour objects ? 1 Answer

Custom Inspector: Using SeralizedProperty changes the prefab values! 0 Answers

Custom Inspector, Collections, SetDirty 0 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