EditorGUI.EndChangeCheck异常:修改参数后字段未及时更新
问题分析与解决方案
核心问题
修改LocArgument列表的value字段时,场景文本和组件的text字段无法实时更新,需折叠/展开Inspector面板才生效;输入value时存在字符延迟(比如输入"Hello",每输入一个字符,显示的是前一步的输入状态);Inspector面板的text字段也不会即时同步组件的最新值。
原因定位
- 序列化属性更新时机错误:在
EditorGUI.EndChangeCheck()触发后直接调用SetText(),但此时serializedObject.ApplyModifiedProperties()还未执行,目标组件的m_arguments仍为旧值,导致本地化计算用了过时参数。 - 多对象编辑未处理:编辑器标记了
[CanEditMultipleObjects],但SetText()只处理了单个target,未遍历所有选中对象。 - TMP Inspector缓存未刷新:TextMeshPro的内置Editor会缓存
text字段值,即使组件的text已更新,Inspector不会自动同步,需手动触发刷新。 - 输入事件循环延迟:输入文本时,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
相关产品推荐
相关产品推荐

