{"record":{"id":"710a340d5a5849c6","repo":"egametang/ET","slug":"unityengine-object-runtimetype-fullname","errorCode":null,"errorMessage":"不支持导出 UnityEngine.Object 类型: {runtimeType.FullName}","messagePattern":"不支持导出 UnityEngine\\.Object 类型: (.+?)","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.config/Scripts/Model/Share/CSharpObjectCodeEmitter.cs","lineNumber":38,"sourceCode":"        }\n\n        public string Emit(object value)\n        {\n            EmitterContext context = new();\n            return this.EmitValue(value, 0, context);\n        }\n\n        private string EmitValue(object value, int indentLevel, EmitterContext context)\n        {\n            if (value == null)\n            {\n                return \"null\";\n            }\n\n            Type runtimeType = value.GetType();\n            if (this.IsUnityObject(runtimeType))\n            {\n                throw new NotSupportedException($\"不支持导出 UnityEngine.Object 类型: {runtimeType.FullName}\");\n            }\n\n            if (this.TryFormatInlineValue(runtimeType, value, out string inlineValue))\n            {\n                return inlineValue;\n            }\n\n            if (!runtimeType.IsValueType)\n            {\n                context.Enter(value, runtimeType);\n            }\n\n            try\n            {\n                if (this.TryGetDictionaryInfo(runtimeType, out DictionaryInfo dictionaryInfo))\n                {\n                    return this.EmitDictionary(runtimeType, dictionaryInfo, value, indentLevel, context);\n                }","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.config/Scripts/Model/Share/CSharpObjectCodeEmitter.cs#L20-L56","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["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.","Exclude the Unity-typed member from export via the emitter's ignore attributes / serialization control so it is skipped.","Split the data: keep pure managed DTOs for export and Unity references in a separate runtime-only mapping."],"exampleFix":"// before\npublic class SkillConfig\n{\n    public ScriptableObject ProjectilePrefab; // UnityEngine.Object -> rejected\n}\n// after\npublic class SkillConfig\n{\n    public string ProjectilePrefabPath; // exportable; resolved at runtime\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static bool IsExportable(Type t) => !typeof(UnityEngine.Object).IsAssignableFrom(t);","tryCatchPattern":null,"preventionTips":["Keep export DTOs free of UnityEngine.Object references; use asset paths/GUIDs instead.","Mark Unity-reference fields [NonSerialized] or excluded from export.","Run Emit on representative samples in a test to catch Unity-typed members early."],"tags":["csharp","unity","config","serialization","code-emitter"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}