Home > Blockchain >  GetComponent of special type?
GetComponent of special type?

Time:09-22

First of all i know Unity have function FindObjectOfType() , but i dont want use this.

I made kind of "ReferenceManager" for all my script references in unity. CameraManager,EventManager,UIManager etc..

These "Managers" never communicate between each other they always comunicate like this. e.g. CameraManager --> ReferenceManager --> EventManager

Currently i have in my ReferenceManager public struct References where i hold all managers references.

My question is : Is there some nice way how can i have 1 method what will return Manager of type i want.?

My Current code :

public class ReferenceManager : MonoBehaviour
{
    [SerializeField]
    public References references = new References(); //all references go throught this struct
    public struct References
    {
        [field: SerializeField]
        public CameraManager cameraManager { get; set; }
        [field: SerializeField]
        public UIManager uiManager { get; set; }
    }
    private void Awake()
    {
        AssignReferences();
    }
    void AssignReferences()
    {
        List<ISystemComponent> systemComponentsList = Reference.GetSystemComponents();
        foreach(ISystemComponent sC in systemComponentsList)
        {
            if(sC.GetType() == typeof(CameraManager))
            {
                references.cameraManager = sC as CameraManager;
            }
            if(sC.GetType() == typeof(UIManager))
            {
                references.uiManager = sC as UIManager;
            }

        }
    }
}
public static class Reference
{
    static List<ISystemComponent> systemComponentList = new List<ISystemComponent>(); //i hold all Managers in this list
    public static void SubscribeSystemComponent(ISystemComponent sC)
    {
        systemComponentList.Add(sC);
    }//any manager can be added to list by this method
    public static List<ISystemComponent> GetSystemComponents()
    {
        return systemComponentList;
    }
}
public interface ISystemComponent
{

}//this connects all managers with interface
public class CameraManager : MonoBehaviour, ISystemComponent //first manager
{
    private void Awake()
    {
        Reference.SubscribeSystemComponent(this);
    }
}
public class UIManager : MonoBehaviour, ISystemComponent //second manager
{
    ReferenceManager rM;
    CameraManager cM;
    private void Awake()
    {
        Reference.SubscribeSystemComponent(this);
    }
    private void Start()
    {
        GetReferences();
    }
    void GetReferences()
    {
        ReferenceManager rM = FindObjectOfType<ReferenceManager>();
        cM = rM.references.cameraManager; ///This way i currectly connect 2 managers   1 manager ---> ReferenceManager ---> 2 manager
    }
}

I want make 1 generic method what will always return Manager of type what i will call for, something like this :

  //Desired example
    ISystemComponent GetReference(/*Ispecify here somehow what type of manager i want*/)
    {
        return /*based of my specification that type will be returned by this method*/
    }

I will be happy for any ideas, thanks.

CodePudding user response:

Call:

 GetISystemComponent<MazeManager>();

Method:

    public static T GetISystemComponent<T>() where T : ISystemComponent
    {
        foreach(ISystemComponent sC in systemComponentList)
        {
            if(sC.GetType().Equals(typeof(T)))
            {
                return (T)sC;
            }
        }
       Debug.LogError(typeof(T)   " - this component type not exist in List of ISystemComponent" );
       return default(T);
    }

CodePudding user response:

I believe Everts' suggestion is to use a Dictionary<Type, ISystemComponent>:

public class ReferenceManager : MonoBehaviour
{
    [SerializeField]
    public References references = new References(); //all references go throught this struct
    public struct References
    {
        [field: SerializeField]
        public CameraManager cameraManager { get; set; }
        [field: SerializeField]
        public UIManager uiManager { get; set; }
    }
    private void Awake()
    {
        AssignReferences();
    }
    void AssignReferences()
    {
        var systemComponentsList = Reference.GetSystemComponents().Values;
        foreach(ISystemComponent sC in systemComponentsList)
        {
            if(sC.GetType() == typeof(CameraManager))
            {
                references.cameraManager = sC as CameraManager;
            }
            if(sC.GetType() == typeof(UIManager))
            {
                references.uiManager = sC as UIManager;
            }

        }
    }
}
public static class Reference
{
    private static Dictionary<Type, ISystemComponent> systemComponentDict = new(); //i hold all Managers in this list
    public static void SubscribeSystemComponent(ISystemComponent sC)
    {
        systemComponentDict.Add(sC.GetType(), sC);
    }//any manager can be added to list by this method
    public static Dictionary<Type, ISystemComponent> GetSystemComponents()
    {
        return systemComponentDict;
    }

    public static T GetISystemComponent<T>() where T : ISystemComponent
    {
        if(!systemComponentsDict.TryGetValue(typeof(T), out var component))
        {
            Debug.LogError(typeof(T)   " - this component type not exist in List of ISystemComponent" );
            component = default(T);
        }
        return component;
    }
}
  • Related