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 JoeCross9 · Jun 27, 2018 at 01:02 AM · editor-scriptingserializedproperty

Editor-Scripting : event for a serialized property changed

Hi guys,

so, I'm trying to make a script, an Editor, that will allow me to change a value - and see the result of the change immediately while in editor mode, e.g. not running the game.

I manage to this, it's working fine - but I cannot escape the feeling that it may be there a more elegant or simpler solution than the one I'm using. I searched extensively the net, but couldn't find a better solution. If I'm missing something, please help.

 public override void OnInspectorGUI()
 {
         serializedObject.Update();
         
         EditorGUI.BeginChangeCheck();
         EditorGUILayout.PropertyField(cardSuite);
         serializedObject.ApplyModifiedProperties();
         if (EditorGUI.EndChangeCheck())
         {
             _cardScript.ChangeSuite();
         }
 
         EditorGUI.BeginChangeCheck();
         EditorGUILayout.PropertyField(cardNumber);
         serializedObject.ApplyModifiedProperties();
         if (EditorGUI.EndChangeCheck())
         {
            _cardScript.ChangeNumber();
         }
 
         EditorGUI.BeginChangeCheck();
         EditorGUILayout.PropertyField(isFlipped);
         serializedObject.ApplyModifiedProperties();
         if (EditorGUI.EndChangeCheck())
         {
            _cardScript.Flip();
         }
 }

"cardNumber" and "cardSuite" are enums type, which will produce dropdown control in the Editor. isFliped is a Boolean value, which will produce a checkbox control in the Editor.

So, this is working fine - but is there a better solution? I imagine this will become a huge mess if there are 10+ properties...

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

3 Replies

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

Answer by JoeCross9 · Jul 16, 2018 at 02:12 AM

So I researched this a little more (for some reason, it didn't give me sleep at night :)) - and I found a better solution. Still, it's not perfect, but I believe this is what Unity devs use, too.

   public SerializedProperty cardSuite;
   public SerializedProperty cardNumber;
   public SerializedProperty isFlipped;
 
   private CardScript _cardScript;
 
   void OnEnable()
   {
       cardSuite = serializedObject.FindProperty ("CardSuite");
       cardNumber = serializedObject.FindProperty ("CardNumber");
       isFlipped = serializedObject.FindProperty("IsFlipped");
   }

 public override void OnInspectorGUI()
 {
      // Update the serializedProperty - always do this in the beginning of OnInspectorGUI.
      serializedObject.Update();

      EditorGUILayout.PropertyField(cardSuite);
      EditorGUILayout.PropertyField(cardNumber);
      EditorGUILayout.PropertyField(isFlipped);
 
      _cardScript = (CardScript)target;
      string _enumVal = cardSuite.enumNames[cardSuite.enumValueIndex];
      if(_cardScript.CardSuite.ToString() != _enumVal)
      {
          _cardScript.ChangeSuite(_enumVal);
      }
        
      _enumVal = cardNumber.enumNames[cardNumber.enumValueIndex];
      if(_cardScript.CardNumber.ToString() != _enumVal)
      {
         _cardScript.ChangeNumber(_enumVal);
      }
 
      if(_cardScript.IsFlipped != isFlipped.boolValue)
      {
            _cardScript.Flip(isFlipped.boolValue);
       }
 
      serializedObject.ApplyModifiedProperties();
 }


Basically, the solution is to compare the values of the serialized property against the value of the current target object.

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
avatar image
1

Answer by JDelekto · Jun 27, 2018 at 01:47 AM

I'm not sure if you need to call the EditorGUI.BeginChangeCheck() and EditorGUI.EndChangeCheck() multiple times; but instead use one call; but if it is required, you can refactor your code to make it easier to handle new properties in the future.

First, define a struct which will hold a reference to your SerializedProperty and an Action delegate to call the method on your _cardScript instance. For the sake of the code below, I'll assume that the type of _cardScript is a class named "CardScript".

     public struct PropertyAction
     {
         public PropertyAction(SerializedProperty property, Action<CardScript> action)
         {
             this.property = property;
             this.action = action;
         }
 
         public SerializedProperty property;
         public Action<CardScript> action;
     }

Create a member in your class which is a list of these "PropertyActions", which you will initialize after you've initialized the SerializedProperty references to cardSuite, cardNumber and isFlipped, like so:

     private List<PropertyAction> propertyActions;

At an appropriate place in your script, after you've retrieved your SerializedProperty references, initialize the list of PropertyAction structs (this only needs to be done once, and to handle new properties, all you need to do is add a new entry to the initializer list. It will look something like this:

     private void Awake()
     {
         // Get references to SerializedProperties here first...
         
         // Initialize property and method delegates
         this.propertyActions = new List<PropertyAction>
         {
             new PropertyAction(cardSuite, (cs) => cs.ChangeSuite()),
             new PropertyAction(cardNumber, (cs) => cs.ChangeNumber()),
             new PropertyAction(isFlipped, (cs) => cs.Flip())
             // Add new property/action combinations here....
         };
     }

Now, at this point, you add code to your OnInspectorGUI() which will iterate through this list and perform the same actions for each property in your list. It will check for the change, apply modified properties and if changed, call the appropriate action on your _cardScript instance. This code only needs to be written once!

     public override void OnInspectorGUI()
     {
         serializedObject.Update();
 
         this.propertyActions.ForEach(propertyAction =>
         {
             EditorGUI.BeginChangeCheck();
             EditorGUILayout.PropertyField(propertyAction.property);
             base.serializedObject.ApplyModifiedProperties();
 
             if (EditorGUI.EndChangeCheck())
             {
                 propertyAction.action(this._cardScript);
             }
         });
     }

If all of your properties follow the same pattern, then all you need to do is add one new entry to the list, which is the SerializedProperty reference and a delegate to call an action on your _cardScript instance. Aside from getting the property reference itself, it's just one new line of code to perform the same operations on that new property.

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 JoeCross9 · Jul 02, 2018 at 03:49 PM 0
Share

Thanks for the reply.

Yes, this is a good way to deal with repetitive code, basically in any program$$anonymous$$g language, thanks.

But, what I was looking for is more Unity oriented solution. Devs from Unity says they are using the same classes to develop editors for general use, so I was wondering how they are dealing with it.

avatar image JDelekto JoeCross9 · Jul 02, 2018 at 06:21 PM 0
Share

$$anonymous$$aybe you are thinking of using a ScriptableObject?

avatar image
0

Answer by squarelover · Feb 16, 2021 at 02:15 PM

alt text


снимок-экрана-2021-02-16-в-165715.png (110.6 kB)
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

99 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

Related Questions

Editor Window: Renaming an object using SerializedProperty 0 Answers

Calling ApplyModifiedProperties results in other variables resetting to 0? 0 Answers

If Check for serialized flag enums in Editor scripting 1 Answer

Get UnityEvent reference from SerializedProperty 1 Answer

How to initialize array[][] via SerializedProperty? 1 Answer


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