Generic Scriptable Object Fields

I was really excited about the new generic serialization update but when I tried it in my case I got an unexpected result.

I have a generic class inheriting from a scriptable object and I also have subclasses that are serialized as concrete types so that I may create .asset files from them.

What I wanted to do was to have a public field of MyGenericSO or something like that and to then get an asset reference field in the inspector. Instead, the inspector showed the direct field of the class type which prevents me from dragging in my asset into the inspector.

Is this by design or will this be resolved in the final release?

Bump

bump

Could you show some example code, and a screenshot of what you see in the Inspector? I’m having trouble picturing what you’re describing.

public class SerlizationTest : MonoBehaviour
{
    public Wrapper<int> wrapper;
    public ScriptableWrapper<int> shouldBeScriptableObject;
    public ConcreteWrapper isSctriptableObject;
}

[System.Serializable]
public class Wrapper<T>
{
    public T value;
}

[System.Serializable]
public class ScriptableWrapper<T> : ScriptableObject
{
    public T value;
}

public class ConcreteWrapper : ScriptableWrapper<int>
{

}

5369580--543411--upload_2020-1-14_13-19-37.png

The code above produces this result in the inspector which doesn’t really make that much sense. The second field should render like the third, not the first so I would call this a bug.

I also get an error in the console:

UnityException: ScriptableObject.ctor is not allowed to be called during serialization, call it from Awake or Start instead. Called from MonoBehaviour ‘SerlizationTest’ on game object ‘GameObject (1)’.
See “Script Serialization” page in the Unity Manual for further details.
UnityEngine.ScriptableObject…ctor () (at <0d01204b437e47c1a78b600b597a89f4>:0)
ScriptableWrapper`1[T]…ctor () (at <247d1935aa774493a25c0b3378dd702d>:0)

1 Like

Agreed, this looks like a bug to me - shouldBeScriptableObjectshould indeed be rendered as a ScriptableObject field instead of expanded like that. Could you use the Bug Reporter to file that as a bug, and paste the number here?

1 Like

The case number is: 1211768

7 Likes

For those of you still coming across this post, the bug has been fixed as of 2020.1.0a22 which, at the time of writing, isn’t publicly available yet but should be soon.

3 Likes

So I just tried Unity 2020.1.0a22 which DOES indeed fix the issue I described above but the functionality isn’t quite complete by the looks of it:

public class SerlizationTest : MonoBehaviour
{
    public Wrapper<int> wrapper;
    public ScriptableWrapper<int> shouldBeScriptableObjectWithInt;
    public ScriptableWrapper<string> shouldBeScriptableObjectWithString;
    public IntWrapper isSctriptableObjectWithInt;
    public StringWrapper isSctriptableObjectWithString;
}

[System.Serializable]
public class Wrapper<T>
{
    public T value;
}

[System.Serializable]
public class ScriptableWrapper<T> : ScriptableObject
{
    public T value;
}

[CreateAssetMenu (menuName = "int wrapper")]
public class IntWrapper : ScriptableWrapper<int>
{

}

[CreateAssetMenu (menuName = "string wrapper")]
public class StringWrapper : ScriptableWrapper<string>
{

}

There’s all my code and this is the result:

5454066--556809--upload_2020-2-7_13-8-2.png

Ultimately, this does now produce fields in the inspector that only accept the correct types but I have 2 comments on this:

  • In the “Should Be Scriptable Object” fields, the type specified on the right should say “Scriptable Wrapper” or whatever the type is for that field rather than “Scriptable Wrapper`1” on both fields regardless of the type
  • In the screenshots below I am dragging an instance of a concrete IntWrapper as a serialised asset over the string fields:
    5454066--556812--upload_2020-2-7_13-13-42.png
    5454066--556815--upload_2020-2-7_13-14-7.png
    The generic field’s UI updates as if it would accept the input even though it DOESN’T accept the input which is actually the CORRECT outcome. In other words, functionally it works but the feedback in the UI is wrong. In the second image I’m dragging an IntWrapper into the StringWrapper field and this UI and outcome is correct. My mouse cursor even becomes a black no entry sign which doesn’t happen in the first image.

Is the team already aware of this? Should I submit another bug report / two bug reports?

3 Likes

Ah, thanks! Please submit a new bug report, yes. I think we’ll probably prioritise this one a little lower than the previous one, as it’s a UI glitch rather than a core data problem, but it should still get fixed.

2 Likes

@JakHussain seriously, thank you. This will be a huge improvement for my workflow knowing this is implemented/fixed, and thank you as well @superpig for responding and helping out too! :smile: Super excited to take advantage of the inspector + generics more now!

1 Like

I’m using 2019.3.05f and I have a SO, which itself has a generic SO field with custom type passed in. This field doesn’t even show in the inspector, is this part of the same problem?

@MrDizzle26 This feature is only available in Unity 2020.1 which is still in alpha so if you really need to use this feature you’ll need to upgrade. I’d suggest keeping a non upgraded version of your project aside in case the alpha causes some irreversible damage to your project (very unlikely).

So I’ve downloaded Unity 2020.1, and my SO field shows in the inspector, but I am unable to assign a generic SO of a derived type to a field that expects a super. So polymorphism doesn’t work for generic references?

public abstract class Effect { }

public class ChildEffect : Effect { }

public abstract class StatEffect : ScriptableObject where T : Effect
{
public T Effect;
}

// This is concrete SO
public class ChildStatEffect : StatEffect { }

public class SomeClass
{
// Unity won’t let me assign ChildStatEffect into this slot in the inspector?
StatEffect StatEffect;
}

1 Like

Try marking the objects that you pass as T to be serialisable? That would likely play a part in generically serialising it. In my example above I’m using primitives which are serialisable by default.

What I wrote here is simplified sudo code in order to better explain my issue, in reality, all my classes are marked [Serializable]

In C#, generics of different types are different classes (they are invariant). If you need to respect inheritance rules, then look into covariant/contravariant generics: https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance

For example,

public interface Invariant<T> { }
public interface Covariant<out T> { }
public interface Contravariant<in T> { }

Invariant<Base> genericBase = default;
Invariant<Derived> genericDerived = default;
genericBase = genericDerived; // err in compiler
genericDerived = genericBase ; // err in compiler

Covariant<Base> genericBase = default;
Covariant<Derived> genericDerived = default;
genericBase = genericDerived ; // compiles
genericDerived = genericBase ; // err in compiler

Contravariant<Base> genericBase = default;
Contravariant<Derived> genericDerived = default;
genericBase = genericDerived ; // err in compiler
genericDerived = genericBase ; // compiles
3 Likes

@JakHussain Have you submitted a bug report regarding the representation of generic arguments in object picker? If so, could you share a link to IssueTracker? I see the bug isn’t fixed yet in 2021, and I failed to find it on IssueTracker. I’d like to vote on it so that it is fixed sooner.

4 Likes

I’m interested in voting on this bug report as well. Has it been submitted by any chance?

Additionally I found that the object picker is not populated as well, even though the implementations exist (2020.3.11f1):
7214659--867235--upload_2021-6-7_16-31-58.png 7214659--867238--upload_2021-6-7_16-32-21.png

1 Like

@EdEddnEddy The issue was ‘fixed’ in 2021.2 Unity Issue Tracker - Assets are not listed in the Object picker field when ScriptableObject is Generic
Now all assets inherited from BaseScriptableEvent appear in the object selector window. However, if you create a BaseScriptableEvent field, BaseScriptableEvent or assets will also appear in the list, so it’s not really a fix. I requested a further fix to which they replied it is more of a feature request than a bug report. They might consider adding it in the future but don’t expect it to be fixed soon

1 Like