Generic MonoBehaviour from assembly

Good day to all.

I have several scripts like

Base<Foo> : MonoBehaviour
MyScript : Base<MyScript>

All works fine, until I don’t try to place them to the mono assembly.

The problem is that the only way to add this kind of scripts is to
use AddComponent in the code. And in the editor script name
is empty. Don’t wanna leave this solution as these scripts contain
serializable fields to be set before use. It would be great if someone
can help me to resolve this issue =)

Feel free to ask questions in comments. I’ll update the post if it can
help you to understand my problem.

Thanks at least for reading =)


EDIT:
Sorry if I was unclear. IT WORKS FINE (SCRIPT MyScript IS SERIALIZED IN EDITOR) IF I DON’T TRY TO COMPILE MY CODE TO A SEPARATE .DLL. So stop post messages like “It’s impossible to serialize such scripts”, please. The issue is not to serialize such kind of scripts, but to use them after compiling to a separate .dll assembly.


EDIT_2:

I had got this trouble when compiled both scripts

Base<Foo> : MonoBehaviour
MyScript : Base<MyScript>

to a separate .dll (both in the same dll, simply added to the project, not loaded at runtime). After adding compiled assembly (.dll file) to the other project, I am able to use all compiled scripts directly in editor(attach to game objects) if they(scripts) are not kind of those I mentioned above (I want anybody who uses this .dll in the project to be able to attach instance of MyScript to any game object directly in editor). I want this dll to work with any platform, so I cannot specify it.


Ok, i did again some tests (the last ones were ages ago). It’s true that Unity can work with concrete classes, even when they are derived from a generic class. However Unity’s DLL importer which looks for MonoBehaviour components seems to generally reject all classes that have a generic super class somewhere up the hierarchy. So while it’s possible to actually use the class, the Editor won’t recognise it as a valid component since no “MonoScript subasset” has been generated for that class.

This is actually a bug in Unitys DLL importer.

In the example case of a Monobehaviour-singleton there are two possible options based on if the singleton is generated on-the-fly or if it’s a scene-based / serialized singleton:

If you don’t need serialization, it should work out of the box. The instance is created when you first access the singleton, just as expected.

If you want to preinitialize the instance you have to create another subclass in the project itself as a dirty workaround.

Example:

// inside our external DLL

public class Singleton<TSelfType> : MonoBehaviour where TSelfType : MonoBehaviour
{
    private static TSelfType m_Instance = null;
    public static TSelfType Instance
    {
        get
        {
            if (m_Instance == null)
            {
                var type = typeof(TSelfType);
                m_Instance = (TSelfType)FindObjectOfType(type);
                if (m_Instance == null)
                {
                    m_Instance = (new GameObject(type.Name)).AddComponent<TSelfType>();
                }
                DontDestroyOnLoad(m_Instance);
            }
            return m_Instance;
        }
    }
}

public class SomeManager : Singleton<SomeManager>
{
    public string someString;
    public int someInt;
    public Transform someOtherObject;
}

When we import this DLL into our project, Unity won’t recognise SomeManager as component. But if we add another script (SomeManagerImp.cs) to our project which contains this class:

// inside our Unity project
using OurDLLNamespace;

public class SomeManagerImp : SomeManager
{
    // empty
}

We can add an instance of this class to a gameobject in the scene and have our serialized instance. The singleton still works fine since this class is a subclass of the singleton.

Unity can’t unity-serialize the types of generic objects. It’s impossible.

I’ve done a few things that need types serialized, and usually I end up going with a string to represent the type (which can be selected from a drop-down if you write a custom editor / property drawer). In your case though, you might have Base : Monobehaviour and MyScript : Base, and then something stupid like BaseLogic< T > : object which just contains the generic functions you need. A Base would create a personal instance of a BaseLogic of its own type (MyScript or Base) and link it to itself.

Dealing with Unity not serializing generics is always yucky, I’d recommend avoid needing generics of serialized Unity-types where possible (MonoBehaviour, ScriptableObject, whatever else).