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 MrDizzle26 · Feb 18, 2020 at 09:20 PM · c#scriptableobjectscriptable objectgenericspolymorphism

Polymorphism with generic ScriptableObjects?

I have a generic scriptable object field of type 'Effect' showing in the inspector, but I am unable to assign a ScriptableObject of the derived type to that field.

Here's my simplified sudo-code example.

 [Serializable]
 public class Effect { }
 
 [Serializable]
 public class DerivedEffect : Effect { }
 
 public class StatEffect<T> : ScriptableObject where T : Effect
 {
     public T Effect;
 }
 
 // This Scriptable Object can't be assigned to fields of type StatEffect<Effect>
 public class DerivedStatEffect : StatEffect<DerivedEffect> { }
 
 public class SomeClass
 {
     // Unity won't let me assign DerivedStatEffect to this slot in the inspector?
     StatEffect<Effect> StatEffect;​
 }

So is it that polymorphism doesn't work for generic references? No Covariance?

Comment
Add comment · Show 1
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 FullMe7alJacke7 · Feb 18, 2020 at 10:49 PM 1
Share

I believe you need to implement an interface on your scriptableObject and use that in combination with your current approach, which can only be done with SerializedReferences in 2019.3.

There should be a way around it though, I recently did something similar and I think I ended up dropping the generics for the interface and using the base class for the inspector level serialization.

1 Reply

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

Answer by Bunny83 · Feb 18, 2020 at 11:52 PM

Covariance does work, however your setup does not represent a valid covariance case. Your types are incompatible.


First of all covariance and contravariance only apply to array types, delegate types and generic type parameters. Array types are a bit special since they allow covariance which is actually not type safe. However generic type parameters have strict constraints how you can use them.


First of all you should keep in mind that two concrete types of a generic type with different type parameters are fundamentally different types. So a List<int> and a List<string> do not have anything in common besides the base class System.Object. The two special contract cases covariance and contravariance only apply to certain "access operations". Covariance does only work on "out" type parameters. That means the generic class can use this type parameter only for return values or out parameters. So it's about the direction of information flow. The prime example for covariance is the IEnumerable<out T> interface. See the documentation. Note the "out" prefix. That means the type "T" can only be used for return values / readonly properties / out parameters. Any usage which allows information flow in the other direction is not allowed. So you can not use this type to define a method parameter, a writeable property or a field.


Contravariance on the other hand is exactly the opposite in the sense of information flow. They only allowed usage of that type is when information flows into the generic type. So only method parameters (any maybe write only properties?!? which would be pretty crazy but possible i think). The prime example for contravariance is System.Action<in T>. Again note the "in" prefix and see the documentation.


You can not have a type parameter have both, "in" and "out" and it also wouldn't make any sense. This is all about type safety. As I said earlier generic types with different type arguments are fundamentally different types. Even when one type is derived from the other. Co- / Contravariance provide a type safe way to allow certain assignments which usually wouldn't work. The only requirement is that typesafety is preserved.


Now have a look at your case Your "StatEffect" variable is of type StatEffect<Effect>. Therefore you will have a field named "Effect" which is of type "Effect". However this is already an issue. You try to assign an instance of your DerivedStatEffect which is of type StatEffect<DerivedEffect>. The field "Effect" in this class is of type "DerivedEffect". So imagine you have another class like this:

 [Serializable]
 public class FooBarEffect : Effect { }

Now imagine this code:

 StatEffect.Effect = new FooBarEffect();

Is this allowed? Yes since The Effect field of our StatEffect class is of type Effect so we can assign a FooBarEffect since it is derived from Effect. Would this be possible when the actual instance behind "StatEffect" is an instance of "DerivedStatEffect" ? No, it would not work because the Effect field in our actual class is of type DerivedEffect and a FooBarEffect is not derived from that. Therefore your types are completely incompatible with each other.


A member field generally models both information flow directions since it can be written to and also read from. So the opposite is also not possible. Imagine that:

 StatEffect<Effect> myObj; // assume we have an instance of that class here.
 myObj.Effect = new FooBarEffect(); // possible since Effect is of type Effect
 
 StatEffect<DerivedEffect> myDerivedStatEffect = myObj;  // this is also NOT possible.

In this case we actually have an isntance of StatEffect<Effect> so its Effect field can happily hold any Effect derived class. However the assignment to "myDerivedStatEffect" is not possible since the field of that type does only allow DerivedEffects.


Some people think about generics just as some fancy way to define some kind of dynamic types. This is not the case. Generic type parameters generally break polymorphism between concrete classes of the same generic type but with different type parameters. The only exception to this rule are co and contravariance and those only work with either "out" or "in" type parameters.


To me it's not really clear what you wanted to achieve with your class setup. What you want to do clearly is not type safe so it's hard to tell what your goal was.

Comment
Add comment · Show 1 · 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 MrDizzle26 · Feb 19, 2020 at 01:41 PM 0
Share

Thanks for the detailed and throughout answer. $$anonymous$$y goal was to have an effects system where I could drag and drop functionality via scriptable objects in the editor. But now I understand the constraints of generics I will look at a new approach.

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

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

An OS design issue: File types associated with their appropriate programs 1 Answer

How to Update ScriptableObject 1 Answer

Null Reference Error With Scriptable Objects 1 Answer

Serialize a list of scriptable objects to Json 0 Answers

How do you save a reference to a prefab's script in a ScriptableObject? 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