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;
}
}