egametang/ET · error · NotSupportedException

不支持导出 UnityEngine.Object 类型: {runtimeType.FullName}

Error message

不支持导出 UnityEngine.Object 类型: {runtimeType.FullName}

What it means

Thrown by CSharpObjectCodeEmitter.EmitValue when the runtime type of a value being exported derives from UnityEngine.Object (GameObject, MonoBehaviour, ScriptableObject, Component, etc.). The emitter generates plain C# object literals, so it cannot represent Unity engine objects, which are native objects with no serializable managed state.

Source

Thrown at Packages/cn.etetet.config/Scripts/Model/Share/CSharpObjectCodeEmitter.cs:38

        }

        public string Emit(object value)
        {
            EmitterContext context = new();
            return this.EmitValue(value, 0, context);
        }

        private string EmitValue(object value, int indentLevel, EmitterContext context)
        {
            if (value == null)
            {
                return "null";
            }

            Type runtimeType = value.GetType();
            if (this.IsUnityObject(runtimeType))
            {
                throw new NotSupportedException($"不支持导出 UnityEngine.Object 类型: {runtimeType.FullName}");
            }

            if (this.TryFormatInlineValue(runtimeType, value, out string inlineValue))
            {
                return inlineValue;
            }

            if (!runtimeType.IsValueType)
            {
                context.Enter(value, runtimeType);
            }

            try
            {
                if (this.TryGetDictionaryInfo(runtimeType, out DictionaryInfo dictionaryInfo))
                {
                    return this.EmitDictionary(runtimeType, dictionaryInfo, value, indentLevel, context);
                }

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Replace the UnityEngine.Object reference with a serializable identifier (asset path string, GUID, or int id) that the emitter can write, and resolve it at runtime.
  2. Exclude the Unity-typed member from export via the emitter's ignore attributes / serialization control so it is skipped.
  3. Split the data: keep pure managed DTOs for export and Unity references in a separate runtime-only mapping.

Example fix

// before
public class SkillConfig
{
    public ScriptableObject ProjectilePrefab; // UnityEngine.Object -> rejected
}
// after
public class SkillConfig
{
    public string ProjectilePrefabPath; // exportable; resolved at runtime
}
Defensive patterns

Strategy: type-guard

Type guard

static bool IsExportable(Type t) => !typeof(UnityEngine.Object).IsAssignableFrom(t);

Prevention

When it happens

Trigger: Calling CSharpObjectCodeEmitter.Emit on an object graph that contains a UnityEngine.Object reference (e.g. a config field holding a ScriptableObject, a MonoBehaviour, or a prefab/GameObject reference).

Common situations: A Luban/Excel-driven config struct gains a field that references a ScriptableObject asset; a designer links a GameObject into a data table; a DTO reused between runtime and export accidentally carries a Unity reference.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/710a340d5a5849c6. Report an issue: GitHub.