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

能否在ScriptableObject中使用UnityEvents/UnityActions并引用层级GameObject?

当然可以啦!我来分两部分给你解答这两个问题:

1. ScriptableObject中使用UnityEvents/UnityActions完全可行

你写的代码本身是完全正确的——UnityEvent和UnityAction在ScriptableObject里是支持序列化的,编辑器里能正常显示这个事件字段,还能直接在Inspector面板中添加回调方法。

不过有几个要注意的点:

  • 如果你的UnityEvent绑定了场景中的组件方法,当场景卸载后这些绑定会失效(因为场景对象被销毁了)
  • 如果需要让ScriptableObject的回调在跨场景时依然有效,建议绑定到单例对象或者资源文件夹中预制体的组件(运行时实例化的那种),这类对象不会随场景卸载被销毁
  • 要是需要带参数的回调,直接用泛型版本的UnityEvent就行,比如public UnityEvent<string> OnDogSpoke;,用法和普通UnityEvent完全一致
2. ScriptableObject持有GameObject引用的两种情况

ScriptableObject可以持有GameObject引用,但要分场景对象和预制体两种情况来看:

  • 引用资源文件夹中的预制体:完全没有问题,序列化和反序列化都正常,运行时也能正确加载,非常适合用来存储需要复用的对象模板
  • 引用场景层级中的GameObject:编辑器里能看到引用,但有不少坑:
    • 场景卸载后,这个引用会直接变成null,因为场景对象已经被销毁了
    • 把ScriptableObject打包成AssetBundle时,场景对象的引用会丢失(场景对象不属于AssetBundle的资源范畴)
    • 如果确实需要引用场景对象,建议在运行时通过代码动态赋值(比如在场景初始化时用GameObject.Find()或者单例模式找到对象后赋值),而不是在编辑器里直接拖,这样能避免意外的空引用问题

你的示例代码可以正常运行,这里再贴出来方便参考:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

[CreateAssetMenu(menuName ="Dog", fileName ="New Dog")]
public class Dog : ScriptableObject 
{
    public string Id;
    public string Text;
    public UnityEvent WhenFinished;
    public GameObject Go;
}

总的来说,你的写法本身是没问题的,只要注意场景对象引用的局限性就行。如果是做跨场景复用的配置,优先用预制体引用,回调绑定到持久化的对象上会更稳妥~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:38:03