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 Or-Aviram · Jun 29, 2016 at 11:41 AM · classescustom editorgenericsproperty drawer

Property draw a class that has a generic type

There isn't much to say... I just want to know if it's possible to property draw a class that has a generic type. If the answer is no just say no (I don't really need an alternative solution, so I don't need to add more detains. I have a different solution, but I don't like it), if it is so how am I suppose to do it?

edit(Moved from answer):

I will just specify what I want, because my other answer won't work:

I have a class called "Attack", which contains some properties an attack has (such as a name, or a cost), and a delegate, which is the method being called when attacking. The delegate is a delegate called "VoidFunc" (when I made it I didn't know about the Action delegate, and what I made is basically a Func delegate without a return type). The Attack class has a few overloads, each one adds one generic, and that generic is the generic type in the delegate. Here is an example for one with one generic type:

 [System.Serializable]
 public class Attack<T>
 {
 
     public string name;
     public int cost;
     public VoidFunc<T> attackMethod;
     
 }

Now I need to make a custom property drawer for this. I have a non-generic overload, which worked perfectly fine, but it is not what I need. My initial attempt was this:

 [CustomPropertyDrawer(typeof(Attack<T>))]
 public class AttackPropertyDrawer<T> : PropertyDrawer

But apparently you can't use generic types in attributes (I would actually like to know the logic behind it)... So I tried instead of making the class generic and put the generic type in the Attack type, just use the object keyword, meaning I will do "Attack". But it didn't work... So I tried something else, to test if it's even possible to draw generic classes... Let's say I made an Attack, ok? So then when I property drawn it, I used "Attack". It still didn't work. So the problem must be Unity's support to it. I came to the forum and got @jdean300's answer, which also didn't work. I now had that different solution of using "object" at the attack class, but I can't overload a variable. So do you have any other solution? The ONLY solution I have left is to use the "object" keyword at the delegate declaration, but I'd prefer almost ANY other solution to do it.

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

Answer by Bunny83 · Jun 29, 2016 at 12:11 PM

Unity's serialization system doesn't support serializing generic types except the generic "List" type. The inspector can only edit things that are serializable by Unity.

edit
Since you have added more details i will get a more detailed answer.

Again, Unity doesn't support serializing generic types. Furthermore delegates can't be serialized by Unity in general. Unity now supports a special delegate wrapper type called "UnityEvent". This class is defined in the "UnityEngine.Events" namespace.

Unity also implemented a generic version of that class in order to specify event parameters. However as i said Unity doesn't support generic types, that's why you have to create a concrete type out of the generic type in order to be serializable.

 [System.Serializable]
 public class EventWithStringParam : UnityEvent<string> { }

You can use generic base classes but the final classes and types that are used have to be concrete, non-generic types if you want them to be serializable and to be viewable / editable in the inspector.

Make sure you read the UnityEvent documentation carefully, especially the last paragraph about the generic type.

Comment
Add comment · Show 8 · 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 Or-Aviram · Jun 29, 2016 at 12:13 PM 0
Share

So how are there some plugins that make the dictionary appear in the inspector? They probably used the PropertyDrawer.

avatar image Bunny83 Or-Aviram · Jun 29, 2016 at 02:47 PM 0
Share

A PropertyDrawer only alters the way how serialized properties are displayed. You can implement a custom editor / inspector for the containing class. A custom editor could display pretty much anything but editing is pretty pointless since the generic classes aren't serialized.

Your question is worded in a very abstract way so it's not clear what you actually want to achieve.

avatar image Or-Aviram · Jun 30, 2016 at 07:01 AM 0
Share

I actually didn't want the methods to appear, though it would be nice... But if I do it, I would like to only have one slot for one method, not a full UnityEvent. But that wasn't even the problem, what I wanted to do is to make them show up (and in a custom way) even without the method.

avatar image Or-Aviram · Jul 01, 2016 at 11:11 AM 0
Share

@Bunny83 So you have no idea? :/

avatar image Bunny83 Or-Aviram · Jul 01, 2016 at 01:27 PM 0
Share

Once and for all: Unity does not support serializing generic types at all with the one and only special excpetion: List<T>.

So if you use a generic parameter in your type definition, no matter if the type is actually used or not, it can't be serialized by Unity and thus can't be edited in the inspector. You have to get rid of your generic parameter if you want it to be visible in the inspector. That's it.There's no way around that.

ps. You again posted an comment as answer. I again converted the answer into a comment but that was the last time. I again advise you to read the user guide and the FAQs

avatar image Or-Aviram Bunny83 · Jul 03, 2016 at 03:24 PM 0
Share

For some reason I didn't get an Email saying I got an answer, so that's why it's so late...

Ok, I read the user guide. The reply I make now might not be good, and maybe it should have been an answer, but the user guide didn't contain anything against it, so let's just hope it will be fine...

I made something like this

 public class AttackWithPlayer : Attack<Player> { }

And then when I made the property drawer, I did it like that:

 [CustomPropertyDrawer(typeof(Attack))]
 [CustomPropertyDrawer(typeof(AttackWithPlayer))]
 public class AttackPropertyDrawer : PropertyDrawer

And the variable I made was like that:

 public AttackWithPlayer testAttack;

You might say I give too much details in code, ins$$anonymous$$d of explaining in sentences, but this is the best way I can show it. I have no idea how, but it doesn't work... $$anonymous$$aybe like it doesn't edit that class even if it's not generic, only because it's base class is generic. How does it make sense? And is it suppose to be like that?

Show more comments
avatar image
5

Answer by ModLunar · Jan 17, 2020 at 04:42 PM

Unity 2020. Still in alpha, but I'm never going back. It was just like this in 2018.3 with Nested Prefabs. WOO!


If you have this for example, as a data class:

 using System;
 using UnityEngine;
 
 [Serializable]
 public class Blah<T> {
     [SerializeField] private T value;
 }


Then you can use the following code snippet for your PropertyDrawer.

 using UnityEditor;
 using UnityEditor;
 
 [CustomPropertyDrawer(typeof(Blah<>))]
 public class BlahDrawer : PropertyDrawer {
     //... (your typical PropertyDrawer stuff here).
 }


Just note your PropertyDrawer should NOT be generic itself, but you can use typeof(Blah<>) without any type in between the angle brackets, to specify any type can go there. This is confirmed to work in Unity 2020.1.0a18 as of today, and thank the heavens.

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
2

Answer by jdean300 · Jun 29, 2016 at 11:54 AM

It's possible with a bit of hacking. The generic class that you want to create a property drawer for needs to inherit from a non-generic base class, and then you can create a property drawer for the non-generic class.

 public class NonGenericBase {}
 
 public class GenericType<T> : NonGenericBase {}
 
 [CustomPropertyDrawer(typeof(NonGenericBase ))]
 public class NonGenericBaseDrawer {}
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 Or-Aviram · Jun 29, 2016 at 12:11 PM 0
Share

That only works with the variables of type NonGenericBase, but when I make a variable of type GenericType, it doesn't draw it. Do you have any other solution?

avatar image PyroIZO · Mar 21, 2017 at 01:26 PM -1
Share

Yes, it's works for class, but you should indicate that the drawer also works for inherited childs: [CustomPropertyDrawer(typeof(NonGenericBase), true)]

Unfortunately, it doesn't works for struct, which couldn't be inherited... I am looking for a custom drawer adapted to System.Nullable

avatar image Boltman · Feb 13, 2020 at 06:02 PM 0
Share

This method doesn't seem to be working in Unity 2019 unfortunately. Though apparently you can do this without workarounds in Unity 2020, but that's not quite fully released yet at this exact moment.

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

49 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

Related Questions

Extended class attributes/methods referenced as base class attributes/methods 1 Answer

Custom editor: Drawing generic properties 1 Answer

I need a dictionary for a custom inspector 0 Answers

Putting a UnityEvent PropertyDrawer into a Custom Editor Window 1 Answer

Cannot get a class to show up correctly in a custom inspector 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