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

Unity 2022.3.3f1泛型Translation System序列化异常问题求助

解决Unity泛型TranslationProperty序列化问题

问题根源

Unity内置序列化系统对泛型类的支持存在限制,即便IntProp是非泛型子类,但其继承链中存在泛型抽象类TranslationProperty<T>,会直接导致序列化失效。另外,ScriptableObject作为资源对象,必须以独立Asset文件的形式存在才能被正确序列化持久化,仅在内存中创建实例无法被Unity序列化保存。

修复方案

1. 清理泛型基类的序列化标记

泛型类本身无法被Unity序列化,移除TranslationProperty<T>上的[Serializable]特性,避免序列化系统混淆。

2. 调整字段定义方式

将自动属性改为普通字段加属性封装,Unity对普通字段的序列化支持更稳定。

3. 实现ScriptableObject的Asset化创建

修改实例创建逻辑,将子类实例保存为Project中的Asset文件,而非仅在内存中生成。

4. 修正编辑器实例创建逻辑

在编辑器中创建并保存ScriptableObject Asset后再赋值给MonoBehaviour字段,确保引用可被序列化。

修改后的代码示例

基础类(TranslationProperty)

using System;
using UnityEngine;

[Serializable]
public abstract class TranslationProperty : ScriptableObject
{
    [SerializeField]
    protected string _name;
    public string Name => _name;

    public abstract void SetValue(object newValue);
    public abstract object GetValue();

    public static T CreateInstance<T>(string assetPath, string name, string value) where T : TranslationProperty
    {
        var instance = CreateInstance<T>();
        instance._name = name;
        instance.Init(value);
        
        #if UNITY_EDITOR
        UnityEditor.AssetDatabase.CreateAsset(instance, assetPath);
        UnityEditor.AssetDatabase.SaveAssets();
        #endif
        
        return instance;
    }

    protected abstract void Init(string value);
    public abstract TranslationProperty Clone();

#if UNITY_EDITOR
    public bool Foldout = false;
    public abstract void OnInspector();
#endif
}

泛型基类(TranslationProperty)

using UnityEngine;
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif

// 移除泛型类的Serializable标记
public abstract class TranslationProperty<T> : TranslationProperty
{
    [SerializeField]
    protected T _value;
    public T Value => _value;

    public override object GetValue() => _value;

    public override void SetValue(object newValue)
    {
        if (newValue is T typedValue)
            _value = typedValue;
    }

    public abstract T Parse(string value);

    public override TranslationProperty Clone()
    {
        TranslationProperty<T> instance = (TranslationProperty<T>)GetInstance();
        instance._name = _name;
        instance.SetValue(_value);
        return instance;
    }

    protected abstract TranslationProperty GetInstance();

    public override string ToString() => _value.ToString();

    protected override void Init(string value) => _value = Parse(value);

#if UNITY_EDITOR
    public override void OnInspector()
    {
        EditorGUILayout.LabelField($"Property {_name}");
    }
#endif
}

子类(IntProp)

using UnityEngine;
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif

[Serializable]
public class IntProp : TranslationProperty<int>
{
    public override int Parse(string value) => int.Parse(value);

    protected override TranslationProperty GetInstance() => CreateInstance<IntProp>();

#if UNITY_EDITOR
    public override void OnInspector()
    {
        EditorGUILayout.BeginHorizontal();
        base.OnInspector();
        _value = EditorGUILayout.IntField(_value);
        EditorGUILayout.EndHorizontal();
    }
#endif
}

测试类(TestTranslation)

using UnityEngine;

public class TestTranslation : MonoBehaviour
{
    public IntProp prop;
}

测试编辑器(TestTranslationEditor)

using UnityEditor;

[CustomEditor(typeof(TestTranslation))]
[CanEditMultipleObjects]
public class TestTranslationEditor : Editor
{
    public override void OnInspectorGUI()
    {
        TestTranslation t = (TestTranslation)target;

        if (t.prop == null)
        {
            string assetPath = $"Assets/IntProp_Prop1.asset";
            t.prop = TranslationProperty.CreateInstance<IntProp>(assetPath, "prop1", "0");
        }

        t.prop.OnInspector();

        EditorUtility.SetDirty(t.prop);
        EditorUtility.SetDirty(t);
    }
}

额外注意事项

  • 所有ScriptableObject子类实例必须保存为Asset文件,才能被Unity正确序列化持久化,退出Play模式后数据不会丢失。
  • 若需运行时动态创建实例并序列化,可考虑用JsonUtility手动序列化数据,或改用普通可序列化类存储数据,避免依赖泛型ScriptableObject的自动序列化。
  • Unity序列化系统仅支持非泛型的可序列化类型,泛型类无法被自动序列化。

内容的提问来源于stack exchange,提问作者Patricio Díaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 11:37:41