Unity Graph View对话节点如何添加静态类函数调用功能
Unity GraphView对话节点静态函数调用功能实现方案
这个需求完全可以实现,你之前尝试的委托、UnityEvent方案失败,主要是因为自定义GraphView节点没有绑定对应的序列化UI,且UnityEvent无法稳定序列化对静态方法、非Unity对象方法的引用,存储到ScriptableObject中容易出现引用丢失的问题,下面是适配你现有架构的可行方案:
1. 扩展序列化数据结构
我们采用字符串存储目标类名+方法名的方案,适配你当前的ScriptableObject存储架构,同时新增自定义属性用于过滤可用的事件类,避免出现无关的系统类选项:
// 新增静态事件类标记属性 [AttributeUsage(AttributeTargets.Class)] public class DialogueEventProviderAttribute : Attribute { }
// 扩展DialogueNodeData public class DialogueNodeData { // 原有字段全部保留 public string GUID; public string DialogueText; public string AnimationName; public bool EntryPoint = false; // 新增事件调用相关字段 public string StaticClassName; public string StaticMethodName; }
// 同步扩展GraphView节点类 public class DialogueNode : Node { public string GUID; public string DialogueText; public string AnimationName; public bool EntryPoint = false; public string StaticClassName; public string StaticMethodName; }
2. 为节点添加类/方法选择UI
在DialogueNode的构造逻辑中新增两个下拉框控件,分别用于选择静态类和对应方法:
- 第一个下拉框的选项列表通过
TypeCache.GetTypesWithAttribute<DialogueEventProviderAttribute>()获取所有标记了属性的静态类全名 - 选中类后,通过反射拉取该类下所有公共静态无参方法,作为第二个下拉框的选项
- 下拉框值变更时同步更新节点对应字段,保存节点数据时写入
DialogueContainer的对应条目即可
示例UI添加代码:
// 放在DialogueNode构造函数中 // 类选择下拉框 var classOptions = TypeCache.GetTypesWithAttribute<DialogueEventProviderAttribute>() .Select(t => t.FullName) .ToList(); var classDropdown = new DropdownField("触发事件类", classOptions, 0); classDropdown.RegisterValueChangedCallback(evt => { StaticClassName = evt.newValue; // 联动更新方法下拉框选项 var methodOptions = Type.GetType(evt.newValue) ?.GetMethods(BindingFlags.Public | BindingFlags.Static) ?.Select(m => m.Name) ?.ToList() ?? new List<string>(); methodDropdown.choices = methodOptions; }); extensionContainer.Add(classDropdown); // 方法选择下拉框 var methodDropdown = new DropdownField("触发方法", new List<string>(), 0); methodDropdown.RegisterValueChangedCallback(evt => { StaticMethodName = evt.newValue; }); extensionContainer.Add(methodDropdown);
3. 运行时调用逻辑
对话流程执行到对应节点时,通过反射调用对应静态方法即可,示例代码:
using System.Reflection; void ExecuteNodeEvent(DialogueNodeData nodeData) { if (string.IsNullOrEmpty(nodeData.StaticClassName) || string.IsNullOrEmpty(nodeData.StaticMethodName)) return; Type targetClass = Type.GetType(nodeData.StaticClassName); if (targetClass == null) return; MethodInfo targetMethod = targetClass.GetMethod(nodeData.StaticMethodName, BindingFlags.Public | BindingFlags.Static); targetMethod?.Invoke(null, null); }
可选优化点
- 可以提前在加载对话配置时缓存所有用到的
MethodInfo,避免运行时重复反射查找,提升性能 - 如果需要支持带参数的方法,可以额外序列化参数值,调用时传入参数数组即可
- 可以添加配置校验逻辑,避免删除类/方法后配置失效的问题
内容的提问来源于stack exchange,提问作者user16602651
相关产品推荐
相关产品推荐

