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
0
Question by NarallandaKaratoga · Aug 02, 2019 at 12:57 PM · editorserializationcustom inspector

Serializale field not being serialized when using reflection?

Recently I Have a script attached to a gameobject, which configure key bindings:

 public class KeyBinding : MonoBehavour
 {
         [Serializable] public struct Setting { public KeyCode key; public CommandType type; }
         [SerializeField] Setting moveLeftSetting;
         [SerializeField] Setting moveRightSetting;
         [SerializeField] Setting jumpSetting;
         [SerializeField] Setting crouchSetting;
         ....
 }

and a custom inspector, using reflections to extract setting variables and change them. The key code uses a different text assignment style, shown as below:

 [CustomEditor(typeof(KeyBinding))]
 public class KeyBindingWindow : Editor
 {
     public override void OnInspectorGUI()
     {
         ....
         foreach(var kb in typeof(KeyBinding).GetFields(BindingFlags.Instance | BindingFlags.NonPublic))
         {
             if(kb.FieldType != typeof(KeyBinding.Setting)) continue;
             var val = (KeyBinding.Setting)kb.GetValue(x);
             ......
             val.type = (CommandType)EditorGUILayout.EnumPopup(val.type, GUILayout.MaxWidth(100));
             .......
             var newVal = EditorGUILayout.TextField(val.key.ToString(), GUILayout.Width(100));
             if(Enum.TryParse<KeyCode>(newVal, true, out var parsedRes)) val.key = parsedRes;
             else val.key = KeyCode.None;
             .......
             kb.SetValue(x, val);
     }
 }

While val.key works perfectly inside the editor, val.key will be set to None every time I open-up Unity editor. However val.type still gets the right value. What goes wrong? What should I do to keep the values?

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
1
Best Answer

Answer by Bunny83 · Aug 02, 2019 at 02:17 PM

You don't change any of the actual values inside your KeyBinding class. Your "Setting" type is a struct. Therefore this line:

 var val = (KeyBinding.Setting)kb.GetValue(x);

will get you a local copy of that struct. Changes to that struct won't change the actual values in your KeyBinding class instance. In order to actually change the values you have to write the whole struct back using SetValue after your change. Also keep in mind that you have to use the Undo class to actually communicate your changes to Unity.


Though your approach using reflection seems to be unnecessary complicated. If you have multiple settings you probably want to use an array. If you really want to have individual setting fields you might want to turn the struct into a class and just add the instances to an array.


Also a PropertyDrawer for your Setting type would probably make more sense. Reflection is almost always a bad idea / the wrong design. Reflection might be unavoidable if you want to access things that are not under your control.

Comment
Add comment · Show 3 · 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 NarallandaKaratoga · Aug 02, 2019 at 02:22 PM 0
Share

I added the kb.SetValue(x, val) things just now. Without this the val.type field would not work, just like the val.key, and I will be unable to change anything in the inspector. But it actually works fine in the editor... And, is Undo affect this behaviour?

avatar image Bunny83 NarallandaKaratoga · Aug 02, 2019 at 05:25 PM 0
Share

You shouldn't use $$anonymous$$arkSceneDirty unless there is no other way. The usual way is to use the SerializedObject / SerializedProperty approach from an inspector. However in your case where you directly mess with the object instances you should use the Undo class like I said. All you have to do is call Undo.RecordObject before you apply any changes to your object. This will make unity to create a temporal serialized snapshot of your object and at the end of the current callback it will automatically make a diff if something has changed and will serialize the object properly. It also creates an undo action for your changes.


Using "$$anonymous$$arkSceneDirty" in an inspector is just plain wrong. You could currently inspect a prefab or scriptableobject that is not part of the current scene. using $$anonymous$$arkSceneDirty would mark the scene dirty even no change has been made and still won't save your changes to the prefab or scriptable object.


It seems a bit strange that you kind of ignored my answer, added the things I've mentioned to your question and then posting your own answer which suggests the wrong approach ^^.


Also there's still no need for reflection. As I mentioned you could have written just a PropertyDrawer for your Setting type. So everywhere where you use a field of type "Setting" Unity would use that PropertyDrawer to display and edit it. Property drawers take some time to get used to because they abstract away all the underlying types. They work directly with the serialized data. They also abstract away editing multiple selected objects at the same time.


Note that a PropertyDrawer now provides different ways how to provide the GUI for a certain property. The old approach uses the I$$anonymous$$GUI system just like you did by overriding OnGUI and GetPropertyHeight. The new version allows you to create GUI elements for the property.

avatar image NarallandaKaratoga Bunny83 · Aug 02, 2019 at 10:41 PM 0
Share

Oh, all right, sorry for my negligence. I didn't get "acturally communicate your changes to Unity" means like that. $$anonymous$$aybe I just didn't get used to the "key nouns with a short useful comment" style tutorial. Thanks for those information.

avatar image
0

Answer by NarallandaKaratoga · Aug 02, 2019 at 02:52 PM

Oh damm I figured it out... I completely forget about this .... EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());

Then if Unity Editor doesn't realize that the scene is changed, pressing Ctrl+S is useless... val.type doesn't work as well, if I don't change other things in the scene....


(About the reflection: (1) I don't need to change inspector files when adding and removing Settings - just making relative things packed, so that people can read and modify it with ease. (2) the re-compilation of editor assembly will not be triggered by modifying KeySetting.)

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

147 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

Related Questions

How to make a Custom inspector? 2 Answers

'Unsupported type' error in custom editor script 4 Answers

Trouble setting the object reference in a property drawer 0 Answers

Preview procedural texture in scene without serializing it? 1 Answer

Don't save gameobjects to scene file (No hide flags) 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