Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 chillersanim · Apr 27, 2014 at 12:49 PM · c#serializationruntimereflection

How to serialize and deserialize components at runtime?

Hello.

I'm working on a dynamic loading system, and need to serialize and deserialize components in the editor and in the runtime.
In the editor, it is easy as there are some classes available, but they aren't available in the runtime.

My aproach was to find all public fields as well as the nonpublic fields where a "SerializeField" attribute is applied to. Then I would serialize those fields with the XMLSerializer.

The problem is, I don't get the fields from any components other than my own.

The code I use to serialize a component:

 public class ComponentContent
 {
     public List<FieldContainer> fields;
 
     public Type componentType;

     // Serializes the component with all it's fields
     public static ComponentContent SerializeComponent(Component component)
     {
         var cc = new ComponentContent();
         var type = component.GetType();
         cc.componentType = type;

         // By using this code, fields is an empty array by most components
         var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic);
         
         foreach (var field in fields)
         {
             // Only use public fields or fields with a SerializeField attribute
             if (field.IsPublic || field.IsDefined(typeof(SerializeField), true))
             {
                 cc.fields.Add(FieldContainer.SerializeField(field.GetValue(component), field.Name));
             }
         }
 
         return cc;
     }
 
     public Component DeserializeComponent()
     {
         // Not yet implemented
         return null;
     }
 }

And the code to serialize a field and store it's values:

 public class FieldContainer
 {
     public string fieldName;
 
     public Type fieldType;
 
     public string fieldValue;
 
     // Serializes the value of the field and returns a setup FieldContainer
     public static FieldContainer SerializeField(object obj, string fieldName)
     {
         var fc = new FieldContainer();
         Type type = obj.GetType();

         // Serializes the field using XmlSerializer
         var xmlSerializer = new XmlSerializer(type);
         using (var textWriter = new StringWriter())
         {
             xmlSerializer.Serialize(textWriter, obj);
             fc.fieldValue = textWriter.ToString();
         }
 
         fc.fieldType = type;
         fc.fieldName = fieldName;
 
         return fc;
     }
 
     // Returns the deserialized value of the field
     public object DeserializeField()
     {
         // Deserializes the stored data to the field value using XmlSerializer
         var xmlSerializer = new XmlSerializer(this.fieldType);
         using (var textReader = new StringReader(this.fieldValue))
         {
             return xmlSerializer.Deserialize(textReader);
         }
     }
 }

Can somebody tell me, why I don't get the fields in most components (In the first script)?

Greetings
Chillersanim

Comment
Add comment · Show 2
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 vexe · Apr 27, 2014 at 01:07 PM 0
Share

I'm not so sure this could would successfully [de]serialize UnityEngine.Objects, since, first of all how do you know that it's safe to just serialize public fields? and, UEObjects fields are not mocked with [SerializeField] - remember, if you want to serialize A where A : $$anonymous$$onoBehaviour you'd have to serialize the stuff that's in $$anonymous$$onoBehaviour too, and since $$anonymous$$onoBehaviour is a Behaviour, which is a Component, which is a Object, you'd have to serialize everything there too - and I'm pretty sure not everything's there is mocked with [SerializeField].

And even though you managed to somehow successfully serialize a UEObject, how are you gonna 'safely' deserialize it? Cause you know, there's a reason why Unity doesn't allow you to create Components with the 'new' operator (using constructors) - that's cause it does some home cooking/ internal prepping for you from the inside - I suspect the deserializer could do these things for you.

Please go on though, I'm very interested in this - Let me know if you have any success :)

avatar image chillersanim · Apr 27, 2014 at 01:11 PM 0
Share

I would be especially interessted to know, how the unity serializer works. I wan't to implement a simillar construct, but one that works also in runtime.

The problem with "SerializeField" is, that I check it after the type.GetFields() call, so that should not be the problem...

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by vexe · Apr 27, 2014 at 12:55 PM

You need to add BindingFlags.Instance.

 var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

EDIT:

The bindings above, do get you the fields you want (if any) - but it seems that UE.Component and many others (Transform, MonoBehaviour, etc) don't have any fields, they're just auto-properties which the compiler turn into set_xxx and get_xxx

alt text

If I were to make a serialization system, I'd probably let the [de]serialization of UEObjects to Unity and handle myself what Unity can't, pretty much like Full Inspector.


transform.png (45.5 kB)
Comment
Add comment · Show 10 · 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 chillersanim · Apr 27, 2014 at 01:07 PM 0
Share

Even with that BindingFlags.Instance, I do not get any fields from components like Transform or $$anonymous$$eshFilter.
They do have fields, do they?

avatar image vexe · Apr 27, 2014 at 01:11 PM 0
Share

Well if you go to their definitions, you'll mostly find auto-properties - which the compiler turns into get_XXX and set_XXX with a backing field - But yea you should get fields, let me try.

avatar image chillersanim · Apr 27, 2014 at 01:14 PM 0
Share

I thought, that the Unity serializer isn't able to serialize properties?
Or is it just not able to serialize customized properties?

avatar image chillersanim · Apr 27, 2014 at 01:20 PM 0
Share

When I use the line:

 var properties = type.GetProperties( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.SetProperty);

... then I find about 40 properties in the Transform component.

But I want to serialize like the unity internal serialize, in order to get the same result.
That is important, because I need to load (and unload) objects like Unity, in order to create the same instantiating behaviour as Unity.
If I don't do that, then there can be problems with the calls of OnEnable etc, because some properties then already have the wrong value...
Also I would call the get/set method of the properties, before the initializing through the OnEnable/Start/Awake and that could lead to errors

avatar image vexe · Apr 27, 2014 at 01:24 PM 0
Share

Why don't you let Unity do it for you? can you talk more about your dynamic loading system, maybe there's another approach you could take? if not, then consider taking a peek at Unity serializer's code.

Show more comments

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

21 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

Related Questions

Cannot convert object[] to Vector3[] 2 Answers

Multiple Cars not working 1 Answer

Serialization at runtime 0 Answers

Distribute terrain in zones 3 Answers

pass child class to ScriptableObject.CreateInstance<> ? 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