Unity3D RPG Core | 19 泛型单例模式
这节内容编写泛型单例类。使用泛型的原因是后续我们还会再创建一些单例类,为了方便我们为单例抽象出一个模板。
1. 编写泛型单例类
我们创建一个新的 C# 脚本,命名为 Singleton。如代码清单 1 所示,我们同样申请静态的 m_instance 以及访问单例的 GetInstance() 函数。
同时此处单例类上下文依托于 Unity 生命周期,所以将相关维护操作放置在 Awake() 和 OnDestroy() 中。进一步感受生命周期对于单例的维护,可以在相关函数上打断点跟踪一下。
要使运行时断点生效,需要在 VS 中选择 “附加到 Unity 并播放”。
第 5 行声明中的 where 关键字是对类型参数的约束,它代表类型 T 必须是继承于 Singleton<T> 的类型。
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class Singleton<T> : MonoBehaviour where T : Singleton<T>
- {
- static T m_instance = null;
- static public T GetInstance()
- {
- return m_instance;
- }
- protected virtual void Awake()
- {
- if (m_instance != null)
- Destroy(gameObject);
- else
- m_instance = (T)this;
- }
- protected virtual void OnDestroy()
- {
- if (m_instance == this)
- {
- m_instance = null;
- }
- }
- }
1.1 改写 MouseManager 类
之前编写的 MouseManager 类是一个单例类,我们对其进行改造。只需使其继承于上述编写的 Singleton 类:
- public class MouseManager : Singleton<MouseManager>
接着再删除 MouseManager 中之前已经定义的和 Singleton 类中逻辑重复的地方即可(m_instance、GetInstance、Awake)。
2. GameManager 开个头
之前我们还遗留一些问题:比如角色人物死亡后,需要执行特定的逻辑。这些游戏整体的逻辑我们放在 GameManager 类中进行控制,同样它也需要是一个单例类。
如代码清单 3 所示,我们同样使 GameManager 继承于 Singleton 类。在 GameManager 中我们需要获取到角色人物的状态信息,通过 RegisterPlayerData() 函数外部指定角色信息变量。
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class GameManager : Singleton<GameManager>
- {
- public CharacterData m_playerData;
- public void RegisterPlayerData(CharacterData playerData)
- {
- m_playerData = playerData;
- Debug.Log("RegisterPlayerData Done.");
- }
- }
如代码清单 3 所示,RegisterPlayerData() 调用的时机,我们放在 PlayerController 类的 Start() 函数中。
- public class PlayerController : MonoBehaviour
- {
- // Start is called before the first frame update
- void Start()
- {
- MouseManager.GetInstance().OnMoveMouseClick += DoMoveAction;
- MouseManager.GetInstance().OnAttackMouseClick += DoAttackAction;
- GameManager.GetInstance().RegisterPlayerData(m_characterData);
- }
- }
最后,要让 GameManager 运行起来。和 MouseManager 一样,如图 1 所示,我们在 Hierarchy 窗体中创建一个空的对象,并将 GameManager 脚本附加在上面。
