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

Unity中如何通过变量引用ScriptableObject动作,避免硬编码?

在C#中通过字符串变量名动态访问ScriptableObject动作的方案

以下是几种替代硬编码switch的可行方案,兼顾灵活性和扩展性:

方案1:反射实现动态属性访问

反射可以直接通过属性名字符串获取对应值,适合追求配置灵活性、调用频率不高的场景。如果需要频繁调用,建议提前缓存映射关系避免重复反射开销。

基础反射写法:

// 假设actions是自定义类实例,比如ItemActions类型
var actionsType = itemScriptableObject.actions.GetType();
// 根据属性名获取属性信息,建议缓存该对象
var actionProperty = actionsType.GetProperty(actionPicker);

if (actionProperty != null)
{
    actionSO = actionProperty.GetValue(itemScriptableObject.actions) as ScriptableObject;
    // 执行动作逻辑
}

缓存映射的优化写法(初始化时一次性反射所有动作):

private Dictionary<string, ScriptableObject> _actionMap;

void Awake()
{
    _actionMap = new Dictionary<string, ScriptableObject>();
    var actionsType = itemScriptableObject.actions.GetType();
    
    // 筛选出所有public的ScriptableObject类型属性
    var actionProperties = actionsType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
        .Where(p => p.PropertyType.IsAssignableFrom(typeof(ScriptableObject)));

    foreach (var prop in actionProperties)
    {
        var action = prop.GetValue(itemScriptableObject.actions) as ScriptableObject;
        if (action != null)
        {
            _actionMap.Add(prop.Name, action);
        }
    }
}

// 点击事件处理器
void OnClick()
{
    if (_actionMap.TryGetValue(actionPicker, out var selectedAction))
    {
        actionSO = selectedAction;
        // 执行动作逻辑
    }
}

方案2:手动维护字典映射(性能最优)

如果动作数量固定或变动不频繁,直接在初始化时手动绑定动作与字符串key,性能比反射更优,逻辑也更直观。

private Dictionary<string, ScriptableObject> _actionMap;

void Awake()
{
    _actionMap = new Dictionary<string, ScriptableObject>
    {
        {"action1", itemScriptableObject.actions.action1},
        {"action2", itemScriptableObject.actions.action2},
        {"action3", itemScriptableObject.actions.action3}
    };
}

// 点击事件处理器
void OnClick()
{
    if (_actionMap.TryGetValue(actionPicker, out var selectedAction))
    {
        actionSO = selectedAction;
        // 执行动作逻辑
    }
}

方案3:修改数据结构(根源解决扩展性)

如果后续需要持续新增动作,建议直接调整ScriptableObject的数据结构,用可配置的键值对替代独立属性,完全摆脱对属性名的依赖。

首先修改ScriptableObject定义:

[Serializable]
public class ActionEntry
{
    public string actionKey;
    public ScriptableObject actionSO;
}

// 在你的ItemScriptableObject类中替换原有actions字段
public List<ActionEntry> actions;

然后初始化时转成字典:

private Dictionary<string, ScriptableObject> _actionMap;

void Awake()
{
    _actionMap = itemScriptableObject.actions.ToDictionary(entry => entry.actionKey, entry => entry.actionSO);
}

后续新增动作只需在Inspector面板中添加ActionEntry条目,无需修改任何代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:14:54