【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工厂模式最佳实践

  1. Inspector配置优先

    • 避免硬编码资源路径
    • 使用[SerializeField]暴露预制体引用
  2. 工厂生命周期管理

    • 场景持久工厂用DontDestroyOnLoad
    • 临时工厂随场景销毁
  3. 错误处理

    public GameObject CreateEnemy(EnemyType type) {
        if (!prefabDict.ContainsKey(type)) {
            Debug.LogError($"未配置 {type} 的预制体");
            return null;
        }
        return Instantiate(prefabDict[type]);
    }
    
  4. 性能优化

    • 高频创建对象使用对象池
    • 复杂初始化采用异步加载

七、实战案例: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工厂模式好处

  1. 资源解耦:客户端不依赖具体预制体
  2. 扩展自由:新增类型无需修改调用方
  3. 配置驱动:Inspector可视化配置
  4. 架构优化
    • 小型项目:简单工厂
    • 中型系统:工厂方法+ScriptableObject
    • 复杂架构:抽象工厂+对象池+异步加载

你可能感兴趣的:(【unity工厂模式(缺实战)】)