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

EditorGUI.EndChangeCheck异常:修改参数后字段未及时更新

问题分析与解决方案

核心问题

修改LocArgument列表的value字段时,场景文本和组件的text字段无法实时更新,需折叠/展开Inspector面板才生效;输入value时存在字符延迟(比如输入"Hello",每输入一个字符,显示的是前一步的输入状态);Inspector面板的text字段也不会即时同步组件的最新值。

原因定位

  1. 序列化属性更新时机错误:在EditorGUI.EndChangeCheck()触发后直接调用SetText(),但此时serializedObject.ApplyModifiedProperties()还未执行,目标组件的m_arguments仍为旧值,导致本地化计算用了过时参数。
  2. 多对象编辑未处理:编辑器标记了[CanEditMultipleObjects],但SetText()只处理了单个target,未遍历所有选中对象。
  3. TMP Inspector缓存未刷新:TextMeshPro的内置Editor会缓存text字段值,即使组件的text已更新,Inspector不会自动同步,需手动触发刷新。
  4. 输入事件循环延迟:输入文本时,Editor的文本框事件还未完成值的提交就触发了SetText(),导致读取到的是上一次的输入状态。

修复后的代码

运行时代码(核心逻辑微调)

public class LocalizedTMP_UGUI : TextMeshProUGUI
{
    [SerializeField] private string m_localizationKey;
    [SerializeField] private List<LocArgument> m_arguments;
    private ILocalization m_localizer;

    private void Awake()
    {
        // 示例:从全局本地化管理器获取实例
        m_localizer = LocalizationManager.Instance;
    }

    public void SetLocalizedText()
    {
        text = m_localizer.GetLocalization(m_localizationKey, m_arguments);
        ForceMeshUpdate(true); // 传入true强制立即更新网格
        EditorUtility.SetDirty(this); // 标记组件为脏,确保修改能被保存
    }
}

[Serializable]
public class LocArgument 
{
    public string name; 
    public string value;

    public LocArgument(string name, string value)
    {
        this.name = name;
        this.value = value;
    }
}

编辑器代码(关键修改)

[CustomEditor(typeof(LocalizedTMP_UGUI))]
[CanEditMultipleObjects]
public class LocalizedTMP_UGUI_Editor : TMP_EditorPanelUI, ITMPEditor
{
    private SerializedProperty m_arguments;
    private SerializedProperty m_localizationKey;
    private string[] m_languages; 
    private int m_languageIndex = 0;
    private ILocalization m_localizer;

    private void OnEnable()
    {
        m_arguments = serializedObject.FindProperty("m_arguments");
        m_localizationKey = serializedObject.FindProperty("m_localizationKey");
        m_localizer = LocalizationManager.Instance;
        m_languages = m_localizer.GetAvailableLocales();
        m_languageIndex = Array.IndexOf(m_languages, m_localizer.CurrentLocale);
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();

        // 语言切换逻辑
        int newLanguageIndex = EditorGUILayout.Popup("Language", m_languageIndex, m_languages);
        if (newLanguageIndex != m_languageIndex) 
        {
            m_localizer.SetWithLocale(m_languages[newLanguageIndex]);
            m_languageIndex = newLanguageIndex;
            UpdateAllTargetsText();
        }

        // 本地化Key与参数编辑
        EditorGUI.BeginChangeCheck();
        EditorGUILayout.PropertyField(m_localizationKey);
        EditorGUILayout.PropertyField(m_arguments, true); // 自动展开列表
        if (EditorGUI.EndChangeCheck())
        {
            // 先应用属性变更,确保组件拿到最新值
            serializedObject.ApplyModifiedProperties();
            UpdateAllTargetsText();
            // 刷新序列化对象,同步Inspector显示
            serializedObject.Update();
        }

        // 绘制TMP内置Inspector面板
        base.OnInspectorGUI();
    }

    private void UpdateAllTargetsText()
    {
        // 遍历所有选中的目标组件
        foreach (var targetObj in targets)
        {
            if (targetObj is LocalizedTMP_UGUI localizedText)
            {
                localizedText.SetLocalizedText();
            }
        }
        // 强制刷新Inspector与场景视图
        Repaint();
        SceneView.RepaintAll();
    }
}

关键修复说明

  • 提前应用属性变更:在EndChangeCheck()触发后先执行serializedObject.ApplyModifiedProperties(),确保组件拿到最新的m_arguments值再执行本地化更新。
  • 多对象编辑支持:通过targets遍历所有选中对象,统一处理文本更新。
  • 强制视图刷新:调用SceneView.RepaintAll()确保场景文本即时刷新,serializedObject.Update()同步Inspector的text字段显示。
  • 解决字符延迟:通过先提交属性变更再计算本地化,避免读取到未完成提交的输入状态。
  • 标记组件为脏:确保修改后的text值能被Unity正确保存到场景文件中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 04:57:08