// 传统方式的问题
public class EnemySpawner : MonoBehaviour {
public GameObject orcPrefab;
void SpawnOrc() {
// 直接依赖具体预制体
GameObject orc = Instantiate(orcPrefab);
}
}
new
GameObject.Instantiate()
创建// 实现
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);
适用场景:小型项目或类型有限的系统(如子弹类型)
// 抽象工厂
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();
适用场景:需要多态创建的敌人系统、技能系统
// 抽象工厂接口
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系统
[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适应性 | 快速原型开发 | 中型系统 | 大型复杂系统 | 配置驱动系统 |
资源管理 | 预制体拖拽 | 预制体拖拽 | 预制体拖拽 | 集中配置 |
典型场景 | 子弹生成 | 敌人生成 | 多阵营角色创建 | 道具系统 |
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);
}
}
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");
}
public class DynamicFactory : MonoBehaviour {
[SerializeField] EnemyFactory easyFactory;
[SerializeField] EnemyFactory hardFactory;
public EnemyFactory GetCurrentFactory() {
return GameManager.Difficulty == Difficulty.Easy
? easyFactory
: hardFactory;
}
}
// 使用
Enemy enemy = GetCurrentFactory().CreateEnemy();
Inspector配置优先
[SerializeField]
暴露预制体引用工厂生命周期管理
DontDestroyOnLoad
错误处理
public GameObject CreateEnemy(EnemyType type) {
if (!prefabDict.ContainsKey(type)) {
Debug.LogError($"未配置 {type} 的预制体");
return null;
}
return Instantiate(prefabDict[type]);
}
性能优化
跳转看实战具体案例(还在写,但是草稿箱满了,先发出这个,具体发布好了,会修改题目)
下面只是一个简单例子
// 道具工厂接口
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);
}
}