游戏开发常用设计模式

发布时间:2026/7/20 13:32:21
游戏开发常用设计模式 引言游戏开发过程中写项目越久越发现一个问题很多代码烂不是因为写的丑而是因为架构没想清楚。一个功能改三遍就开始牵一发动全身越改越想重写。设计模式就是用来解决这个问题。接下来我将讲讲游戏开发常用的设计模式。单例模式(Singleton)解决什么全局唯一的管理器到处都能方便的调用。坑不要滥用只有真正全局唯一的才用单例玩家属性背包这些别做单例不然做成双人游戏欲哭无泪。还有一个容易被忽略的点场景切换时用DontDestroyOnLoad保留的对象如果切换回主菜单再重新开始要注意清理旧状态。实现//继承MonoBehavior需要挂载到场景依赖Unity生命周期 public class SingletonMonoT : MonoBehavior where T : MonoBehavior { private static T instance; private static bool applicationIsQuit false; public static T Instance { get { if(applicationIsQuit) { Debug.LogWarning($[Singleton] {typeof(T)} 已退出); return null; } if(instance null) { instance FindObjectOfTypeT(); if(intance null) { GameObject go new GameObject(); instance go.AddComponentT(); go.name $(Singleton) {typeof(T)}; DontDestroyOnLoad(go); } } return instance; } } protected virtual void OnDestroy() { applicationIsQuit ture; } }//纯C#类适用于纯逻辑的管理类 public class SingletonT : where T : class,new() { private static T instance; private static readonly object _lock new object(); public static T Instance { get { if(instance null) { lock(_lock) { if(instance null) { instance new T(); } } } return instance; } } }对象池模式(ObjectPool)解决什么游戏中频繁实例和销毁产生的GC卡顿如子弹特效等。坑归还前需要将对象恢复到初始状态(位置旋转等)池子容量要根据峰值调整频繁扩容就失去池的意义了。实现public class ObjectPool : MonoBehavior { [SerializeField] private GameObject prefab; [SerializeField] private int pool_Size 20; private QueueGameObject pool new QueueGameObject(); private void Awake() { for(int i 0;i pool_Size;i) { GameObject obj CreateNewObject(); obj.SetActive(false); pool.Enqueue(obj); } } private GameObject CreateNewObject() { GameObject obj Instantiate(prefab,transform); return obj; } public GameObject Get() { if(pool.Count 0) { GameObject obj pool.Dequeue(); obj.SetActive(true); return obj; } return CreateNewObject(); //池子不够就扩容 } public void Return(GameObject obj) { obj.SetActive(false); obj.transform.SetParent(transform); pool.Enqueue(obj); } public void Clear() { while(pool.Count 0) { GameObject obj pool.Dequeue(); if(obj ! null) { Destroy(obj); } } } public void Reset() { Clear(); for(int i 0;i pool_Size;i) { GameObject obj CreateNewObject(); obj.SetActive(false); pool.Enqueue(obj); } } }观察者模式(Observer)解决什么解耦事件触发者和响应者。观察者模式让玩家只管触发事件谁关心谁自己去订阅。坑如果订阅后忘了取消被观察者销毁时可能报空引用。实现//被观察者(玩家) public class Player : MonoBehavior { public event System.Actionint OnLevelUp; //新等级 private int level 1; private int exp 0; public void AddExp(int value) { exp value; if(exp level * 100) { level; exp 0; OnLevelUp?.Invoke(level); //触发事件 } } }//观察者 成就系统 public class AchievementSystem : MonoBehavior { [SerializeField] private Player player; [SerializeField] private int targetLevel; private vodi Start() { player.OnLevelUp OnLevelHandler; } private void OnLevelHandler(int newLevel) { if(newLevel targetLevel) { Debug.Log($解锁新成就达到{targetLevel}级); } } private void OnDestroy() { player.OnLevelUp - OnLevelUpHandler; } }工厂模式(Factory)解决什么把对象的创建逻辑集中管理调用方不关心怎么创建。坑不要过度设计工厂里生成的对象要自己管理生命周期不管销毁。实现public enum EnemyType { Goblin, Dragon, Slime } public class EnemyFactory : MonoBehavior { [SerializeField] private GameObject prefab_Goblin; [SerializeField] private GameObject prefab_Dragon; [SerializeField] private GameObject prefab_Slime; public GameObject CreateEnemy(EnemyType type) { switch(type) { case EnemyType.Goblin : return Instantiate(prefab_Goblin); case EnemyType.Dragon : return Instantiate(prefab_Dragon); case EnemyType.Slime : return Instantiate(prefab_Slime); default : return null; } } }策略模式(Strategy)解决什么消灭大量if-else和switch。策略模式把每种行为抽成独立的策略运行时动态切换。坑策略类会膨胀每种新闻都要创建新类。实现//定义策略接口 public interface IAtkStrategy { void Execute(Transform atker); }//实现具体策略(做成ScriptObject配置表) [CreateAssetMenu(menuName Strategies/SwordAtk)] public class SwordAtk : ScriptObject,IAtkStrategy { [SerializeField] private float dmg 10f; [SerializeField] private float range 2f; public void Execute(Transform atker) { //近战判定逻辑 } }//使用 public class Player : MonoBehavior { [SerializeField] private IAtkStrategy strategy; public void Atk() { strategy?.Execute(transform); } //运行时切换策略如切换武器 public void SetStrategy(IAtkStrategy newStrategy) { strategy newStrategy; } }