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
9
Question by TKS_Keeper · Feb 06, 2012 at 02:05 AM · c#inspectorserializationgenerics

Serializable class using generics

I have a problem with a recently modified class not showing up in the inspector.

I am attempting to make a class which I can use to automatically stitch up generic list of key/value pairs into a dictionary. However, I am unable to get the class to show up in the inspector when it is added to a behavior. This was working, until I modified the class to act more like a data container by modifying the logic to allow for the getData and setData methods.

I am including the new non-functioning code, as well as an example behavior that I was using to test.


 [System.Serializable]
 public class MapList<Key, Data>
 {
 
 
     //Should never be accessed directly in code
     //but needs to be public for serialization
 
     public List<Link> maps;        
 
     public Link nullLink;
 
     private Dictionary<Key, Link> m_dict;
 
     protected Dictionary<Key, Link> stitchedDict{
         get{
             if (
                 this.maps == null
                  || this.m_dict == null
                 || this.maps.Count != this.m_dict.Count
             ) {
 
                 restitchDict ();
 
             }
 
             return this.m_dict; 
 
         }
 
         set{ this.m_dict = value; }
 
     }
 
 
     public Data getData (Key key)
     {
 
         if (this.stitchedDict.ContainsKey (key)) {
 
             return this.stitchedDict[key].data;
 
         } else {
 
             return this.nullLink.data;
 
         }
 
     }
 
 
     public void setData (Key _key, Data _data)
     {
         if (this.stitchedDict[_key] == null) {
 
             Link dataMap = new Link ();
 
             dataMap.key = _key;
 
             dataMap.data = _data;
 
             this.addMap (dataMap);
 
             this.restitchDict ();
 
         } else {
 
             this.stitchedDict[_key].data = _data;
 
         }
 
     }
 
 
     protected void restitchDict ()
     {
 
         if(this.m_dict == null){
 
             this.m_dict = new Dictionary<Key, Link> ();
 
         }
 
         this.m_dict.Clear ();
 
         this.validateMaps ();
 
         foreach (Link nextMap in this.maps) {
 
             this.m_dict[nextMap.key] = nextMap;
 
         }
 
     }
 
 
     protected void addMap (Link _dataMap)
     {
 
         this.validateMaps ();
 
         this.maps.Add (_dataMap);
 
     }
 
 
     protected void validateMaps ()
     {
 
         if (this.maps == null) {
 
             this.maps = new List<Link> ();
 
         }
 
     }
 
     
 
     //INTERNAL CLASSES
     [System.Serializable]
     public class Link
     {
 
         public Key key;
 
         public Data data;
 
     }
 
 }



 public class ExecBehavior : MonoBehaviour {
     
     public MapList<string, int> exampleMap;
     public List<string> compare1;
     public List<int> compare2;
 
     // Use this for initialization
     void Start () {
     
     }
     
     // Update is called once per frame
     void Update () {
     
     }
 }


Comment
Add comment · Show 3
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 syclamoth · Feb 06, 2012 at 03:47 AM 1
Share

You can't serialize generic classes in Unity. Sorry.

avatar image flamy · Feb 06, 2012 at 03:51 AM 0
Share

@syclamoth , is there any specific reason for this? even i tried sometime back and failed in this

avatar image Immanuel-Scholz · Jun 21, 2013 at 08:07 PM 1
Share

is there any specific reason for this

Lazyness? Its definetely not rocket since to serialize and recreate generic types. Did this before. Unity doesn't support correct aliasing either (which is much harder), so I guess the guy who wrote the serialization framework just isn't that good.

Anyway, you can drive around the problem by just subclassing from your generic like this:

 // Unlike $$anonymous$$apList this will be correctly serialized.
 [System.Serializable] public class $$anonymous$$apListStringInt : $$anonymous$$apList<string,int> {}

3 Replies

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

Answer by andrey_bryzgalov · Jul 26, 2012 at 04:20 PM

You can not serialize a class using the Unity serializer if it has fields with generics.

 [Serializable]
 public class GenericClass<T>
 {
   public T someField;
 }

 [Serializable]
 public class SomeClass
 {
    public GenericClass<string> stringClassField; //does not serialize
 }


However you can define subclasses for constructed generic types:

 [Serializable]
 public class GenericClassOfString : GenericClass<String>
 {
 }
 
 [Serializable]
 public class SomeClass
 {
    public GenericClassOfString stringClassField; //serializes
 }
Comment
Add comment · Show 7 · 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 rhys_vdw · Sep 25, 2012 at 05:46 AM 0
Share

Great solution.

avatar image TMPxyz · Dec 21, 2012 at 09:33 AM 1
Share

splendid, how did you find it out?

avatar image manu3d · Jul 19, 2013 at 10:32 PM 0
Share

Hmmmm. I just tried to make this solution work for a Dictionary but to no avail. Did it perhaps work with previous versions of Unity? Can you show a fuller example, with both the base/child classes and a functioning, serializing inspector? It would be much appreciated.

avatar image rhys_vdw · Jul 22, 2013 at 04:07 AM 1
Share

@manu2d Dictionaries will never show up in the inspector, unfortunately.

The best you can do is to create a list of objects with a key and value and use it to initialize your dictionary.

This solution is for using your own defined generic types.

avatar image manu3d · Jul 22, 2013 at 01:26 PM 0
Share

Hey, give me my third dimension back! I am manu3d, not 2d! ;)

Concerning Dictionaries not showing up in the inspector, this is not entirely correct. Of course it is correct that the default inspector is not capable of displaying dictionaries. However, I have an open question on the subject and the custom inspector I've posted correctly shows the content of the dictionary in the inspector. BUT... the content is deleted as soon as I switch from Edit to Game mode, a serialization problem by my understanding.

Also, I tried to use this solution in the context of the values of the dictionary being a custom type. But so far I can't even get a Dictionary[string,int] to serialize correctly, never $$anonymous$$d my own custom class.

Show more comments
avatar image
8

Answer by Bunny83 · Feb 06, 2012 at 03:50 AM

Unity uses it's own serialization which doesn't support generic types because that would be the hell to implement. Even a class like this can't be serialized by Unity just because it has a generic parameter:

 [System.Serializable]
 public class TestClass<T>
 {
     public int number;
 }

Furthermore you used your internal Link class in your List, but Link depends on one of your generic parameters. Now i dare you to write a serializer that can handle this setup ;)

Generics work way different to c++ templates where it's just a search&replace at compile time. Generics are compiled as they are. It's even hard to describe how they work ;)

Comment
Add comment · Show 6 · 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 flamy · Feb 06, 2012 at 04:10 AM 1
Share

wow thanks for the info :) .. i didnt think that serializing a generic variable would take this much

avatar image Bunny83 · Feb 06, 2012 at 01:19 PM 0
Share

Well, it seems easy, but Unity doesn't do a string or xml serialization. Unity uses their own binary format, so you have to deter$$anonymous$$e the type of each item. In the OPs case above, what do you think is the typename of the internal class $$anonymous$$apList<int,float>.Link ?

The sort "Name" is just Link which doesn't say anything about the used type or if the internal class is affected by any generic parameter or not.

The "FullName" looks like this:

$$anonymous$$apList`2+Link[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, Public$$anonymous$$eyToken=b77a5c561934e089],[System.Single, mscorlib, Version=2.0.0.0, Culture=neutral, Public$$anonymous$$eyToken=b77a5c561934e089]]

Now have fun to serialize the type of this class ;)

Nobody said that's impossible to create a general serializer, but generics allow really nasty constructs like generics in generics in generics. If you have to analyse this with reflection you have to give up at some point.

avatar image GuyLSmith · Feb 19, 2012 at 01:15 AM 9
Share

Bunny83 wrote: "because that would be the hell to implement"

Never an adequate excuse for failing to implement a basic feature. Shame on the Unity dev $$anonymous$$m!

avatar image vexe · Jan 05, 2014 at 03:34 PM 2
Share

+100000000000000 @GuyLSmith

avatar image atr0phy · Mar 31, 2015 at 10:48 PM 0
Share

@GuyLSmith Hit the nail right on the head. Serialization in Unity is a complete mess of a nightmare. Those of us paying good money for Pro should never have to hear excuses like "Eh..it's too hard, so we aren't going to bother. Deal with it."

Show more comments
avatar image
4

Answer by vexe · Jan 04, 2015 at 11:11 AM

Generic type serialization alone with all the cases Unity doesn't support is what I offer in VFW. I make use of ISerializationCallbackReceiver and FullSerializer to write a better custom serialization system. Sick of the fact that Unity's not taking action towards this subject. While there are private individual solutions, they're either kept private or sold at the asset store. This stuff should be available to us out of the box let alone a free downloadable package.

In VFW you could go wild and even serialize nested generic types, so you could write (not that this is realistic, but just to give you a flavor of what you can do):

 public class Test : BetterBehaviour
 {
    [Serialize] // makes it both serializable and thus exposed 
    private Dictionary<Tuple<string, int>, List<IOwner<GameObject>>> dictionary { get; set; }
 }
 
 public interface IOwner<T>
 {
    T Value { get; set; }
 }


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

14 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

Related Questions

Array not updating in inspector 0 Answers

Serialize custom multidimensional array from Inspector 3 Answers

Distribute terrain in zones 3 Answers

Make a public variable with a private setter appear in inspector 3 Answers

How to control the exposure of public variables in the inspector pane based on a value of another variable? 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