如何在Serializable对象中存储方法引用并实现脚本间调用
在Unity可序列化对象中存储方法引用的解决方案
方案一:使用UnityEvent(最简便的可视化方案)
Unity自带的UnityEvent是可序列化类型,能直接在Inspector面板中拖拽绑定目标方法,适合无参或简单参数的场景。
修改你的CallInput类:
using UnityEngine; using UnityEngine.Events; [CreateAssetMenu(fileName = "NewCallInput", menuName = "Data/New Call Input")] public class CallInput : ScriptableObject { // 定义可序列化的事件,用于存储方法引用 public UnityEvent callMethod; }
步骤说明:
- 定义目标方法(ScriptA):
public class ScriptA : MonoBehaviour { // 待调用的目标方法 public void TargetMethod() { Debug.Log("ScriptA的目标方法被执行"); } }
- 调用方法(ScriptB):
public class ScriptB : MonoBehaviour { public CallInput callInput; // 触发调用的方法 public void TriggerMethodCall() { // 空值判断后执行事件 callInput.callMethod?.Invoke(); } }
- Inspector赋值:
- 在Project窗口右键创建
Data/New Call Input实例; - 选中该实例,在Inspector的
callMethod字段中,拖拽场景中的ScriptA对象,选择其TargetMethod绑定; - 在ScriptB的Inspector中,将创建好的CallInput实例拖入
callInput字段。
方案二:带参数的UnityEvent(处理有参方法)
如果需要传递参数,需自定义泛型UnityEvent的子类(默认泛型UnityEvent无法序列化):
// 自定义带int参数的可序列化事件 [System.Serializable] public class IntParameterEvent : UnityEvent<int> {} [CreateAssetMenu(fileName = "NewCallInput", menuName = "Data/New Call Input")] public class CallInput : ScriptableObject { public IntParameterEvent callMethodWithInt; }
对应使用示例:
- ScriptA的目标方法:
public void TargetMethodWithInt(int inputValue) { Debug.Log($"收到参数:{inputValue}"); }
- ScriptB的调用代码:
public void TriggerParameterCall() { callInput.callMethodWithInt?.Invoke(123); }
方案三:自定义可序列化委托(高灵活性方案)
如果需要更灵活的逻辑(比如返回值、复杂参数组合),可以结合[SerializeReference](需Unity 2020.1+)和接口实现:
- 定义调用接口:
public interface IMethodCall { void Execute(); // 可扩展带返回值的方法,比如:int ExecuteWithReturn(); }
- 实现具体的方法调用类:
[System.Serializable] public class ScriptAMethodWrapper : IMethodCall { // 引用目标脚本实例 public ScriptA targetScript; public void Execute() { targetScript?.TargetMethod(); } }
- 修改CallInput类:
[CreateAssetMenu(fileName = "NewCallInput", menuName = "Data/New Call Input")] public class CallInput : ScriptableObject { [SerializeReference] public IMethodCall callMethod; }
- ScriptB调用:
public void TriggerCustomCall() { callInput.callMethod?.Execute(); }
优点:
- 支持复杂逻辑和返回值;
- 可扩展多种不同的方法调用实现。
内容的提问来源于stack exchange,提问作者Patrick W. McMahon
相关产品推荐
相关产品推荐

