Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Unity singleton base class to support generics?

classes deriving relations

In my project, I have a class structure as shown in the image.

The green classes are old codes, that runs very well. The classes in red boxes are newly added codes. There're no compiler errors, however when click play in Unity and runs into the new code, the three classes can't be initialized correctly.

And unity console gives warning that says "The class named 'DataMgrBase`2' is generic. Generic MonoBehaviours are not supported! UnityEngine.GameObject:AddComponent()" at this line: "instance = obj.AddComponent ();"

How can I solve this problem?

Following are some code for your reference, thanks!

Implementation of singleton base class:

using UnityEngine;
using System.Collections;

public class UnitySingletonPersistent<T> : MonoBehaviour where T : Component
{
    private static T instance;

    public static T Instance {
        get {
            if (instance == null) {
                instance = FindObjectOfType<T> ();
                if (instance == null) {
                    GameObject obj = new GameObject ();
                    obj.name = typeof(T).Name;
                    obj.hideFlags = HideFlags.DontSave;
                    instance = obj.AddComponent<T> ();
                }
            }
            return instance;
        }
    }

    public virtual void Awake ()
    {
        DontDestroyOnLoad (this.gameObject);
        if (instance == null) {
            instance = this as T;
        } else {
            Destroy (gameObject);
        }
    }
}

Implementation of DataMgrBase:

public class DataMgrBase<TKey, TValue>: UnitySingletonPersistent<DataMgrBase<TKey, TValue>> {

    protected Dictionary<TKey, TValue> dataDict;

    public override void Awake()
    {
        base.Awake();

        dataDict = new Dictionary<TKey, TValue>();
    }

    public TValue GetDataForKey(TKey key)
    {
        TValue data;
        if (dataDict.TryGetValue(key, out data))
        {
            return data;
        }
        else
        {
            data = LoadDataForKey(key);
            if (data != null)
            {
                dataDict.Add(key, data);
            }

            return data;
        }
    }

    virtual protected TValue LoadDataForKey(TKey key)
    {
        if (dataDict.ContainsKey(key))
        {
            return GetDataForKey(key);
        }
        else
        {
            return default(TValue);
        }
    }    
}
like image 719
ArtS Avatar asked Oct 30 '22 07:10

ArtS


1 Answers

I've solved it by myself as following:

Change of the base class to get a new generic type(of the class that will derive from it, and pass this type to singleton base class)

public class DataMgrBase<TKey, TValue, TClass>: UnitySingletonPersistent<TClass> where TClass: Component

For all the other three classes that want to derive from it, change them as following form:

public class MobSettingDataMgr : DataMgrBase<int, MobSettingData, MobSettingDataMgr>
like image 164
ArtS Avatar answered Nov 08 '22 04:11

ArtS