You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity泛型工厂模式优化咨询:避免重复类型参数

Unity工厂类实现优化建议

问题场景

我正尝试在Unity中实现一个基工厂类,它包含一组带不同ID的预制体实例列表,需要为游戏实现多个不同的工厂,每个工厂对应各自的预制体列表。

已定义通用接口ICreatable,传入ID时工厂会找到对应预制体并返回实例化对象,但当前实现存在冗余问题:创建子类工厂时需要重复传入相同的类型参数(比如AmmoFactory : BaseFactory<BaseAmmo, BaseAmmo>),希望得到优化方案。


现有代码

ICreatable接口

public interface ICreatable<T> where T : MonoBehaviour
{
    #region Properties

    public int Id { get; }
    public T Item { get; }

    #endregion Properties
}

BaseFactory基类

public class BaseFactory<T, U> where T : MonoBehaviour where U : ICreatable<T>
{
    #region Variables

    protected T cachedItem;
    protected U cachedCreatable;

    protected List<U> creatableList;

    #endregion Variables

    #region Functions

    public BaseFactory(List<U> creatableList)
    {
        this.creatableList = new List<U>(creatableList);
    }

    ~BaseFactory()
    {
        creatableList = null;
    }

    public T Manufacture(int id)
    {
        cachedCreatable = GetCreatable(id);
        cachedItem = UnityEngine.Object.Instantiate(cachedCreatable.Item, null);

        return cachedItem;
    }

    private U GetCreatable(int id)
    {
        for (int i = 0; i < creatableList.Count; i++)
        {
            cachedCreatable = creatableList[i];

            if (cachedCreatable != null && cachedCreatable.Id == id)
            {
                return cachedCreatable;
            }
        }

        return default;
    }

    #endregion Functions
}

现有子类工厂写法

public class AmmoFactory : BaseFactory<BaseAmmo, BaseAmmo> { }

优化方案

1. 简化泛型约束,消除重复类型参数

重新设计接口,让实现类自身继承MonoBehaviour并实现ICreatable,这样工厂类只需单个泛型参数:

调整后的ICreatable接口

public interface ICreatable
{
    int Id { get; }
    GameObject Prefab { get; } // 直接返回预制体,或保持泛型约束
}

// 或者保持泛型但让T同时继承MonoBehaviour和ICreatable<T>
public interface ICreatable<T> where T : MonoBehaviour, ICreatable<T>
{
    int Id { get; }
    T Item { get; }
}

优化后的BaseFactory类

以无泛型接口为例,工厂类简化为单泛型参数,同时用字典提升查找效率:

public class BaseFactory<T> where T : MonoBehaviour, ICreatable
{
    private readonly Dictionary<int, T> _creatableMap;

    public BaseFactory(List<T> creatableList)
    {
        // 初始化时转字典,将查找复杂度从O(n)降到O(1)
        _creatableMap = creatableList.Where(item => item != null)
                                     .ToDictionary(item => item.Id, item => item);
    }

    public T Manufacture(int id)
    {
        if (_creatableMap.TryGetValue(id, out var creatable))
        {
            return UnityEngine.Object.Instantiate(creatable.Item, null);
        }
        Debug.LogError($"未找到ID为{id}的可创建对象");
        return null;
    }
}

优化后的子类工厂写法

public class AmmoFactory : BaseFactory<BaseAmmo> { }

2. 移除不必要的缓存字段

原工厂类中的cachedItem和cachedCreatable属于实例级临时变量,每次Manufacture都会被覆盖,没有缓存价值,建议直接移除,避免内存占用和潜在空引用问题。

3. 删除冗余析构函数

Unity中MonoBehaviour对象的生命周期由引擎管理,手动在析构函数中设置creatableList = null无意义,还可能增加GC开销,直接删除即可。


内容的提问来源于stack exchange,提问作者Roduraz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 12:17:19