**不继承MonoBehavior的单例模式基类**…
**继承MonoBehavior的单例模式基类**
自动挂载版:
“`c#
public class SingletonMonoAuto
{
private static T instance;
public static T Instance
{
get
{
if (instance == null)
{
GameObject obj = new GameObject();
obj.name = typeof(T).ToString();
instance = obj.AddComponent
}
return instance;
}
}
}
“`
**[安全问题] 单例模式唯一性 – 构造函数**
针对非Mono
因为继承MonoBehaviour的类本身就不能被new,所以这里主要说不继承的单例基类
1.将基类设置成抽象类,则基类不能被new
2.将子类设置一个private构造器
3.基类用反射来获取构造器创建实例,因为步骤2不再能使用new
“`c#
public class Singleton
{
private static T instance;
public static T Instance
{
get
{
if(instance == null)
{
ConstructorInfo info = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic,
null,
Type.EmptyTypes,
null);
if (info != null)
instance = info.Invoke(null) as T;
else
Debug.LogError(“不存在private私有构造器”);
}
return instance;
}
}
}
“`
**[安全问题] 单例模式唯一性 – 重复挂载**
针对挂载Mono
[DisallowMultipleComponent]
同一物体上不能挂载多个组件,不能根治(不常用)
在awake获取instance前判空即可
“`c#
if(instance != null)
{
Destory(this); // 销毁多余组件
return;
}
“`
**[安全问题] 单例模式线程安全 – 是否加锁**
针对非Mono
继承Mono的类不允许使用多线程
**公共Mono模块**
作用:
1.通过事件或委托,让不继承MonoBehaviour的脚本也能进行相关生命周期函数更新
2.为不继承MonoBehaviour的脚本提供协同程序开启或关闭的方法
3.统一管理帧更新等相关逻辑,提高性能
**缓存池(对象池)模块**
分为柜子(Dictionary),抽屉(List,Stack,Queue等)容器
方法:
public GameObject GetObj(string name)
public void PushObj(GameObject obj)
public void ClearPoor()
– 窗口布局优化
使用静态变量 public static bool isOpenLayout = true;
若为true,在每个对象首次初始化创建其根对象
在子对象失活时移入根对象,在子对象激活时移除根对象
– 对象上限优化
在GetObj方法中加入可选参数MaxUsedObject设置最大激活物体上限
协同开发时为统一上限,可以为每个Perfab单独挂载一个脚本用于设置最大上限,在PoolMgr中获取并在没有挂载时LogError
“`c#
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public class PoolData
{
public Stack
public List
private GameObject dataRoot;
public int Count => stk.Count;
public int UsedCount => usedList.Count;
public void SetDataRootParent(GameObject obj)
{
if (dataRoot == null) dataRoot = new GameObject();
dataRoot.transform.SetParent(obj.transform);
}
public void SetDataRootName(string name)
{
if (dataRoot == null) dataRoot = new GameObject();
dataRoot.name = name;
}
public GameObject Pop()
{
GameObject obj;
if (Count > 0)
{
obj = stk.Pop();
}
else
{
obj = usedList[0];
usedList.RemoveAt(0);
}
usedList.Add(obj);
if(PoolMgr.isOpenLayout)
obj.transform.SetParent(null);
return obj;
}
public void Push(GameObject obj)
{
if (PoolMgr.isOpenLayout)
obj.transform.SetParent(dataRoot.transform);
stk.Push(obj);
usedList.Remove(obj);
}
}
public class PoolMgr : Singleton
{
public static bool isOpenLayout = true;
private PoolMgr()
{
if(PoolMgr.isOpenLayout)
{
poolRoot = new GameObject();
poolRoot.name = “Pool”;
}
}
public Dictionary
private GameObject poolRoot;
public GameObject GetObj(string name, int maxUsedObject = 50)
{
GameObject obj;
if(dic.ContainsKey(name) && (dic[name].UsedCount > maxUsedObject || dic[name].Count > 0))
{
obj = dic[name].Pop();
obj.name = name;
obj.SetActive(true);
}
else
{
if (!dic.ContainsKey(name))
{
// 如果没有抽屉,创建抽屉
PoolData data = new PoolData();
if (PoolMgr.isOpenLayout)
{
data.SetDataRootParent(poolRoot);
data.SetDataRootName(name);
}
dic.Add(name, data);
}
// 实例化新对象
Debug.Log(dic[name].UsedCount);
obj = GameObject.Instantiate(Resources.Load
obj.name = name;
dic[name].usedList.Add(obj);
}
return obj;
}
public void PushObj(GameObject obj)
{
if (PoolMgr.isOpenLayout)
if (poolRoot == null)
{
poolRoot = new GameObject();
poolRoot.name = “Pool”;
}
obj.SetActive(false);
dic[obj.name].Push(obj);
}
public void ClearPoor()
{
dic.Clear();
if (PoolMgr.isOpenLayout)
poolRoot = null;
}
}
“`
**事件中心模块**
通过一个中心化机制,使多个系统,模块,对象之间进行==松耦合通信==,再结合观察者设计模式构成了事件中心模块
使用private Dictionary
方法:
AddEventListener(string eventName, UnityAction func)
RemoveEventListener(string eventName, UnityAction func)
Clear()
Clear(string eventName)
传参优化:
– 使用UnityAction
– 缺点:在值和引用类型转化的过程中存在==装箱拆箱,浪费性能==,因此不推荐使用
– 自定义一个抽象EventInfoBase类作为父类(目的是可以创建多个自定义个参数的EventInfo封装UnityAction来使用),取代字典中的UnityAction(在创建字典时==确定了委托参数类型,避免了装箱拆箱==)
– public class EventInfo : EventInfoBase 作无参数UnityAction的封装
– public class EventInfo
事件名优化:
– 使用枚举类型来代替字符串传入参数名和字典查询事件
“`c#
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public abstract class EventInfoBase { };
public class EventInfo
{
public UnityAction
public EventInfo() { }
public EventInfo(UnityAction
{
actions += func;
}
}
public class EventInfo : EventInfoBase
{
public UnityAction actions;
public EventInfo() { }
public EventInfo(UnityAction func)
{
actions += func;
}
}
public class EventCenter : Singleton
{
private EventCenter() { }
private Dictionary
#region 一参数委托
public void EventTrigger
{
if (dic.ContainsKey(eventName))
{
(dic[eventName] as EventInfo
}
}
public void AddEventListener
{
if (!dic.ContainsKey(eventName))
dic.Add(eventName, new EventInfo
(dic[eventName] as EventInfo
}
public void RemoveEventListener
{
if (dic.ContainsKey(eventName))
{
(dic[eventName] as EventInfo
}
}
#endregion
#region 无参数委托
public void EventTrigger(string eventName)
{
if(dic.ContainsKey(eventName))
{
(dic[eventName] as EventInfo).actions?.Invoke();
}
}
public void AddEventListener(string eventName, UnityAction func)
{
if (!dic.ContainsKey(eventName))
dic.Add(eventName, new EventInfo());
(dic[eventName] as EventInfo).actions += func;
}
public void RemoveEventListener(string eventName, UnityAction func)
{
if (dic.ContainsKey(eventName))
{
(dic[eventName] as EventInfo).actions -= func;
}
}
#endregion
public void Clear()
{
dic.Clear();
}
public void Clear(string eventName)
{
if(dic.ContainsKey(eventName))
{
dic.Remove(eventName);
}
}
}
“`
**资源加载模块**

评论(0)
暂无评论