Unity3D:自动脚本管理器聚合器

介绍


本文将重点讨论脚本管理器之间交互的一种组织类型(称为单调),特别是使用单独的聚合器类,其中包含指向所有实例管理器的链接。阅读本文后,我想到了创建聚合器类的想法

任务


我得出的结论是,每次都用自己的笔将管理人员召集到聚合器类中是非常不便的。创建新的经理时,您将必须打开聚合器类并进行更改。有了足够的经验,您可以使这些繁琐的过程自动化。因此,设置了任务:自动创建单音及其自动收集器。

类单身


using UnityEngine;
public class Singleton<T>: MonoBehaviour where T: MonoBehaviour
{
	public static T instance { get; private set; }

	public void Awake()
	{
		if (instance == null)
		{
			instance = GetComponent<T>();
			ManagersAregator.addManager(instance);
		}
		else
		{
			Debug.Log($"<color=red>   {typeof(T).ToString()}</color>");
			Destroy(gameObject);
		}
	}

	public void OnDestroy()
	{
		ManagersAregator.removeManager<T>();
	}
}

Unity中的经典单例实现使用实例静态变量Awake()方法检查实例是否已定义。如果不是,我们使用this关键字获得对类实例的引用。但是由于在一个特定的实现,类的“模板”变量牛逼使用,不能被使用。但是我们可以很容易地从脚本挂起的对象中获取T组件。如果实例被定义,那么它必须被销毁。因此,该对象在单个副本中将始终处于舞台上。

Awake()方法中将一个新元素添加到聚合器类,并在OnDestroy()方法中,将该元素从聚合器类中删除。

创建MyClass类的单例如下:

public class MyClass: Singleton<MyClass>

如果需要MyClass类中使用Awake()方法,则需要使用base关键字有关base和继承的更多信息):

new void Awake()
	{
		base.Awake(); //  Awake() -
		// 
	}

类聚合器


using System.Collections.Generic;
using UnityEngine;

public static class ManagersAregator
{
	static Dictionary<string, MonoBehaviour> Managers = new Dictionary<string, MonoBehaviour>();

	public static void addManager<T>(T newManager)
	{
		string keyWord = typeof(T).ToString();

		if(Managers.ContainsKey(keyWord))
		{
			Debug.Log($"[ManagersAregator]  -{newManager}-   -{keyWord}-  ");
		}
		else
		{
			Managers.Add(keyWord, newManager as MonoBehaviour);
			Debug.Log($"<color=green>[ManagersAregator]    -{newManager}-   -{keyWord}-</color>");
		}
	}

	public static T getManager<T>(string callback) where T: Singleton<T>
	{
		string keyWord = typeof(T).ToString();

		if(Managers.ContainsKey(keyWord))
		{
			Debug.Log($"<color=yellow>[{callback}]   -{keyWord}-</color>");

			MonoBehaviour mbTemp = null;
			T manager = null;

			if(Managers.TryGetValue(keyWord, out mbTemp))
			{
				manager = (T)mbTemp;
				Debug.Log($"<color=green>[{callback}]  -{manager}- </color>");
			}
			else
			{
				Debug.Log($"<color=red>[{callback}]    -{keyWord}-</color>");
			}

			return manager;
		}

		Debug.Log($"<color=red>[ManagersAregator]    -{keyWord}-   .</color>");
		return null;
	}

	public static void removeManager<T>()
	{
		string keyWord = typeof(T).ToString();

		if(Managers.ContainsKey(keyWord))
		{
			Managers.Remove(keyWord);
			Debug.Log($"[ManagersAregator]    -{keyWord}-   ");
		}
		else
		{
			Debug.Log($"[ManagersAregator]    -{keyWord}-   .");
		}
	}
}

该类是静态的,即他不能在舞台上实例。因此,可以随时从任何场景使用它。

所有脚本管理器(单行)都存储在“ 管理器”字典中。每个管理员的密钥是该管理员的类名。也许刚接触编程的人会问一个问题:“ B,但是此词典存储了MonoBehaviour,而所有类都继承自Singleton吗?”。这是一个很好的问题,答案是实现任何类别的经理自动聚集器的关键。

在编程中,存在向上转换的概念-将类型转换为基类。由于Unity中的所有类都继承自MonoBehaviour它们可以应用于MonoBehabiour因此,Managers词典仅包含MonoBehaviour类的对象

考虑聚合器类的方法:

void addManager<T>(T newManager)

SingletonAwake()方法调用此方法参数是实例类的静态变量接下来,通过实例所属的类的名称创建一个键,并将管理器添加到字典中。

T getManager<T>(string callback) where T: Singleton<T>

该函数将调用该方法的类的名称作为字符串作为参数。这是专门为方便调试而完成的(控制台显示调用该方法的类)。AnotherMyClass类中使用此方法的示例

public class AnotherMyClass: MonoBehaviour
	void Start()
	{
		string cb = GetType().ToString(); //     
		MyClass MC = ManagersAregator.getManager<MyClass >(cb);
	}

控制台中将挂起一条消息:Hu ** I,重做 [AnotherMyClass] Manager -MyClass-已收到。”

void removeManager<T>()

如果 字典中包含类型T的管理器,则将其删除

摘要


实际上,在聚合器类的三个函数中,开发人员只需要使用getManager方法一个特别的优点是在所有情况下调试消息的可见性都很好。当然,您也可以选择关闭它们。我相信,在什么时候查看哪个班级正在尝试获得什么以及它试图获得什么将会非常方便。

希望本文对您有用,并且您发现对自己有用的东西!

All Articles