【unity工厂模式(缺实战)】
·
Unity工厂模式
一、设计由来:Unity对象创建的痛点
1. Unity对象创建的特殊性
// 传统方式的问题
public class EnemySpawner : MonoBehaviour {
public GameObject orcPrefab;
void SpawnOrc() {
// 直接依赖具体预制体
GameObject orc = Instantiate(orcPrefab);
}
}
- 强耦合:调用方依赖具体预制体
- 扩展困难:新增类型需修改调用代码
- 资源管理混乱:预制体引用分散在各脚本
2. Unity引擎限制
- MonoBehaviour不能直接
new - 必须通过
GameObject.Instantiate()创建 - 预制体需预先拖拽或路径加载
二、核心设计思想
1. 控制反转(IoC)
2. 职责分离
- 创建职责:工厂负责实例化和初始化
- 使用职责:客户端仅调用接口
3. 配置驱动
- 通过Inspector配置预制体映射
- ScriptableObject存储创建规则
三、Unity工厂模式分类与实现
1. 简单工厂模式
// 实现
public class EnemyFactory : MonoBehaviour {
[SerializeField] GameObject orcPrefab;
[SerializeField] GameObject goblinPrefab;
public GameObject CreateEnemy(EnemyType type) {
switch(type) {
case EnemyType.Orc:
return Instantiate(orcPrefab);
case EnemyType.Goblin:
return Instantiate(goblinPrefab);
default:
throw new ArgumentException();
}
}
}
// 使用
factory.CreateEnemy(EnemyType.Orc);
适用场景:小型项目或类型有限的系统(如子弹类型)
2. 工厂方法模式
// 抽象工厂
public abstract class EnemyFactory : MonoBehaviour {
public abstract Enemy CreateEnemy();
}
// 具体工厂
public class OrcFactory : EnemyFactory {
[SerializeField] GameObject orcPrefab;
public override Enemy CreateEnemy() {
GameObject obj = Instantiate(orcPrefab);
return obj.GetComponent<Orc>(); // 返回具体组件
}
}
// 客户端
OrcFactory orcFactory = GetComponent<OrcFactory>();
Enemy orc = orcFactory.CreateEnemy();
适用场景:需要多态创建的敌人系统、技能系统
3. 抽象工厂模式
// 抽象工厂接口
public interface ICharacterFactory {
GameObject CreateWarrior();
GameObject CreateMage();
}
// 具体工厂 - 人类阵营
public class HumanFactory : MonoBehaviour, ICharacterFactory {
[SerializeField] GameObject humanWarriorPrefab;
[SerializeField] GameObject humanMagePrefab;
public GameObject CreateWarrior() => Instantiate(humanWarriorPrefab);
public GameObject CreateMage() => Instantiate(humanMagePrefab);
}
// 具体工厂 - 精灵阵营
public class ElfFactory : MonoBehaviour, ICharacterFactory {
// 类似实现...
}
适用场景:多阵营角色系统、不同风格的UI系统
4. ScriptableObject工厂
[CreateAssetMenu(menuName = "Factories/ItemFactory")]
public class ItemFactory : ScriptableObject {
[SerializeField] Item[] itemPrefabs;
public Item CreateItem(ItemType type) {
Item prefab = itemPrefabs.FirstOrDefault(i => i.Type == type);
return Instantiate(prefab);
}
}
// 使用(在MonoBehaviour中)
[SerializeField] ItemFactory itemFactory;
Item potion = itemFactory.CreateItem(ItemType.HealthPotion);
优势:
- 独立于场景存在
- 支持热重载配置
- 多场景共享
四、模式对比与选型指南
| 维度 | 简单工厂 | 工厂方法 | 抽象工厂 | ScriptableObject工厂 |
|---|---|---|---|---|
| 扩展性 | 修改工厂类 | 新增工厂子类 | 新增工厂实现类 | 修改SO配置 |
| 复杂度 | ★☆☆☆☆ | ★★★☆☆ | ★★★★☆ | ★★☆☆☆ |
| Unity适应性 | 快速原型开发 | 中型系统 | 大型复杂系统 | 配置驱动系统 |
| 资源管理 | 预制体拖拽 | 预制体拖拽 | 预制体拖拽 | 集中配置 |
| 典型场景 | 子弹生成 | 敌人生成 | 多阵营角色创建 | 道具系统 |
五、Unity特优实践方案
1. 对象池集成工厂
public class PooledEnemyFactory : MonoBehaviour {
[SerializeField] GameObject orcPrefab;
private Queue<GameObject> orcPool = new Queue<GameObject>();
public GameObject GetOrc() {
if (orcPool.Count > 0) {
GameObject orc = orcPool.Dequeue();
orc.SetActive(true);
return orc;
}
return Instantiate(orcPrefab);
}
public void ReturnOrc(GameObject orc) {
orc.SetActive(false);
orcPool.Enqueue(orc);
}
}
2. Addressables异步工厂
public class AsyncWeaponFactory : MonoBehaviour {
public async Task<Weapon> CreateWeapon(string weaponKey) {
// 异步加载预制体
GameObject prefab = await Addressables.LoadAssetAsync<GameObject>(weaponKey).Task;
GameObject instance = Instantiate(prefab);
return instance.GetComponent<Weapon>();
}
}
// 调用
async void Start() {
Weapon sword = await factory.CreateWeapon("weapons/sword");
}
3. 状态驱动的动态工厂
public class DynamicFactory : MonoBehaviour {
[SerializeField] EnemyFactory easyFactory;
[SerializeField] EnemyFactory hardFactory;
public EnemyFactory GetCurrentFactory() {
return GameManager.Difficulty == Difficulty.Easy
? easyFactory
: hardFactory;
}
}
// 使用
Enemy enemy = GetCurrentFactory().CreateEnemy();
六、Unity工厂模式最佳实践
-
Inspector配置优先
- 避免硬编码资源路径
- 使用
[SerializeField]暴露预制体引用
-
工厂生命周期管理
- 场景持久工厂用
DontDestroyOnLoad - 临时工厂随场景销毁
- 场景持久工厂用
-
错误处理
public GameObject CreateEnemy(EnemyType type) { if (!prefabDict.ContainsKey(type)) { Debug.LogError($"未配置 {type} 的预制体"); return null; } return Instantiate(prefabDict[type]); } -
性能优化
- 高频创建对象使用对象池
- 复杂初始化采用异步加载
七、实战案例:RPG道具系统简单举例
跳转看实战具体案例(还在写,先发出这个,具体发布好了,会修改题目)
下面只是一个简单例子
// 道具工厂接口
public interface IItemFactory {
Item CreateItem(ItemData data);
}
// 具体工厂
public class EquipmentFactory : IItemFactory {
public Item CreateItem(ItemData data) {
var item = Instantiate(data.Prefab).GetComponent<Equipment>();
item.Initialize(data.Stats); // 根据数据初始化
return item;
}
}
// 使用
public class Chest : MonoBehaviour {
[SerializeField] ItemData[] possibleItems;
[SerializeField] EquipmentFactory equipmentFactory;
public Item Open() {
ItemData data = possibleItems[Random.Range(0, possibleItems.Length)];
return equipmentFactory.CreateItem(data);
}
}
总结:Unity工厂模式好处
- 资源解耦:客户端不依赖具体预制体
- 扩展自由:新增类型无需修改调用方
- 配置驱动:Inspector可视化配置
- 架构优化:
- 小型项目:简单工厂
- 中型系统:工厂方法+ScriptableObject
- 复杂架构:抽象工厂+对象池+异步加载
更多推荐

所有评论(0)