Unity中设计模式

张开发
2026/4/4 8:27:44 15 分钟阅读
Unity中设计模式
单例模式什么是单例模式确保一个类只有一个实例有一个全局访问点【static】用途当多个对象需要共享同一资源【GameManagerAudioManager】时用单例可以避免重复创建和资源冲突。避免频繁创建和销毁重量级对象降低内存占用和性能开销。有两种常见形式懒汉饿汉区别在于实例创建的时机懒汉式在第一次调用获取实例的方法时才创建对象实现了延迟加载但在多线程环境下需要处理线程安全问题如加锁、双重检查锁或静态内部类等方式。public class BaseManagerT where T : new() { private static T instance; public static T GetInstance() { if (instance null) instance new T(); return instance; } }饿汉式在类加载时就已经完成实例的创建天生线程安全但可能造成资源浪费如果一直未被使用。public class BaseManagerT where T : new() { private static T instance new T(); // 类加载时即创建实例 public static T GetInstance() { return instance; } }缓存池【对象池模式】在对象需要频繁创建和销毁的情况下使用提高复用性,来优化性能。简易缓存池using System.Collections; using System.Collections.Generic; using UnityEngine; public class easyPoolMgr : BaseMgreasyPoolMgr { public Dictionarystring, ListGameObject pooldic new Dictionarystring, ListGameObject(); public GameObject GetObj(string name) { GameObject obj null; if (pooldic.ContainsKey(name)pooldic[name].Count 0)//这里pooldic[name].Count 0条件忘记加了 { obj pooldic[name][0]; pooldic[name].RemoveAt(0); //Remove和RemoveAt不一样RemoveAt传入的是下标 } else { obj GameObject.Instantiate(Resources.LoadGameObject(name)); obj.name name; } //激活 obj.SetActive(true); return obj; } public void PushObj(string name, GameObject obj) { if (pooldic.ContainsKey(name)) { pooldic[name].Add(obj); } else { pooldic.Add(name, new ListGameObject() { obj }); } //失活 obj.SetActive(false); } }进阶缓存池using System.Collections; using System.Collections.Generic; using UnityEngine; public class poolData { public GameObject fatherContainer; public ListGameObject poolList; public poolData(GameObject obj, GameObject poolContainer) { poolList new ListGameObject(); fatherContainer new GameObject(obj.name); fatherContainer.transform.SetParent(poolContainer.transform); //容易忘 //入池的时候发现没有对应池子。-----》就要生成池子调用构造函数------》因为是入池子的时候触发的所以要触发一次入池 PushObj(obj); } //执行取对象方法 public GameObject GetObj() { GameObject obj null; //取出第一个 obj poolList[0]; poolList.RemoveAt(0); //解绑父子关系 obj.transform.parent null; //激活 obj.SetActive(true); return obj; } //执行入池方法 public void PushObj(GameObject obj) { //失活 obj.SetActive(false); //绑定父子关系 obj.transform.parent fatherContainer.transform; //入池 poolList.Add(obj); } } public class poolManager : BaseMgrpoolManager { //对象池名和对象池存储空间的键值对 public Dictionarystring, poolData pooldic new Dictionarystring, poolData(); //对象池根节点 public GameObject poolContainer; //调度池中对象做判断语句 public GameObject GetObj(string name) { GameObject obj null; //如果有指定的池子且池子里有对象 if (pooldic.ContainsKey(name) pooldic[name].poolList.Count 0) { //执行取对象方法 obj pooldic[name].GetObj(); } else { //如果没有指定的对象创建一个对象 obj GameObject.Instantiate(Resources.LoadGameObject(name)); //该对象改名为路径名 obj.name name; } //返回对象 return obj; } //入池调度 public void PushObj(string name, GameObject obj) { //忘记了 //判断是否有对象池根节点如没有则创建一个 if (poolContainer null) { poolContainer new GameObject(poolContainer); } //如果有对应的存储空间 if (pooldic.ContainsKey(name)) { //执行入池操作 pooldic[name].PushObj(obj); } else { //如果没有则通过池名和根节点---创造一个池子 pooldic.Add(name, new poolData(obj, poolContainer)); } } //清理对象池--切场景时调用 public void clear() { pooldic.Clear(); poolContainer null; } }事件中心【观察者模式】简易事件中心using System.Collections.Generic; using UnityEngine.Events; public class easyEventCenter : BaseMgreasyEventCenter { //UnityActionT1T2 的意思是委托存储的是传入参数为T1T2的函数。且UnityAction是没有返回值的。如果要有返回值得使用Func private Dictionarystring,UnityActionobjecteventDic new Dictionarystring,UnityActionobject(); //添加事件监听-----------可以在其他脚本的Start调用 public void AddEventListener(string name, UnityActionobject action) { //有没有对应的监听 //有监听 if (eventDic.ContainsKey(name)) { eventDic[name] action; } else//无监听 { eventDic.Add(name,action); } } //移除事件监听,防止内存泄露-------可以在其他脚本的OnDestroy调用 public void RemoveEventListener(string name, UnityActionobject action) { if (eventDic.ContainsKey(name)) { eventDic[name] - action; } } //事件触发 public void EventTrigger(string name,object info) { if (eventDic.ContainsKey(name)) { eventDic[name].Invoke(info); } } //主要用在场景切换 public void Clea() { eventDic.Clear(); } }优化事件中心【里氏替换原则优化拆箱装箱】using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; public interface IEventInfo { } public class EventInfoT : IEventInfo { public UnityActionT actions; public EventInfo(UnityActionT action) { this.actions action; } } public class EventInfo : IEventInfo { public UnityAction actions; public EventInfo(UnityAction action) { this.actions action; } } public class EventCenter : BaseManagerEventCenter { //key--事件的名字 //value--对应的是监听这个事件对应的委托函数们 private Dictionarystring, IEventInfo eventDic new Dictionarystring, IEventInfo(); //添加事件监听传事件名和委托函数 public void AddEventListenerT(string name, UnityActionT action) { if (eventDic.ContainsKey(name)) //该事件有监听的情况 { (eventDic[name] as EventInfoT).actions action; } else //该事件没有监听的情况 { eventDic.Add(name, new EventInfoT(action)); } } //重载添加事件监听--无参数 public void AddEventListener(string name, UnityAction action) { if (eventDic.ContainsKey(name)) //该事件有监听的情况 { (eventDic[name] as EventInfo).actions action; } else //该事件没有监听的情况 { eventDic.Add(name, new EventInfo(action)); } } //取消监听--非常重要不移除监听可能会导致内存泄露 public void RemoveEventListenerT(string name, UnityActionT action) { if (eventDic.ContainsKey(name)) { (eventDic[name] as EventInfoT).actions - action; } } //重载取消监听--无参数 public void RemoveEventListener(string name, UnityAction action) { if (eventDic.ContainsKey(name)) { (eventDic[name] as EventInfo).actions - action; } } //事件触发,传要触发的事件名 public void EventTriggerT(string name,T info) { if (eventDic.ContainsKey(name)) { if ((eventDic[name] as EventInfoT).actions ! null) { (eventDic[name] as EventInfoT).actions.Invoke(info); } } } //重载事件触发--无参数 public void EventTrigger(string name) { if (eventDic.ContainsKey(name)) { if ((eventDic[name] as EventInfo).actions ! null) { (eventDic[name] as EventInfo).actions.Invoke(); } } } //清空事件中心可以用于场景切换防内存泄露 public void Clear() { eventDic.Clear(); } }

更多文章