UI Text is not being rebuilt/updated in edit mode, when changing text from OnInspectorGUI

I have a MonoBehaviour which references a UnityEngine.UI.Text component and contains an UpdateText() method. When I call this method from within my custom inspector, the UI Text text value is changed correctly in the inspector, but the text mesh is not updated in the scene or game view.

When I resize any window in the editor, the text display updates. Apparently, there is some sort of rebuild/repaint call that I need to do manually, but I couldn’t figure out which one. Does anyone have experience with this type of custom UI modifications and can tell me the correct procedure?

I’ve tried: Inspector.Repaint(), SceneView.RepaintAll(), Text.Rebuild(), Canvas.ForceUpdateCanvases(), but none of these called worked.

Thanks for any ideas!

Edit

Here is my original problematic code:

using UnityEngine;
using UnityEngine.UI;

public class LocalizedText : MonoBehaviour
{
	public Text targetText;
	public string myString = "Bla Bla";

	public void UpdateText()
	{
		targetText.text = myString;
	}
}

[CustomEditor(typeof(LocalizedText))]
public class LocalizedTextEditor : UnityEditor.Editor
{
	public override void OnInspectorGUI()
	{
		base.OnInspectorGUI();

		if(GUILayout.Button("UpdateText"))
		{
			LocalizedText locaText = (LocalizedText)target;
			locaText.UpdateText();

			// Things I've tried adding to this:
			Repaint();
			UnityEditor.SceneView.RepaintAll();
			locaText.targetText.Rebuild(CanvasUpdate.Prelayout);
			Canvas.ForceUpdateCanvases();
			locaText.targetText.SetAllDirty();
			// + basically any combination of things I could update or force to rebuild on UI components...
		}
	}
}

As said earlier, the “targetText” component updates correctly in the inspector (meaning I can see the TextArea/TextField change in the inspector), but it wouldn’t redraw the actual text mesh in the scene or game view.

Of course, soon after posting, I realized another mistake/missing feature: Undo…

if(GUILayout.Button("UpdateText"))
{
	LocalizedText locaText = (LocalizedText)target;

	UnityEditor.Undo.RecordObject(locaText.targetText, "Update text");
	locaText.UpdateText();
}

The documentation states that Undo.RecordObject is the correct way to handle this and that it will also mark the object as dirty, so I wouldn’t need to use anything else. However, this didn’t solve my problem.

This code does in fact solve my issue:

if(GUILayout.Button("UpdateText"))
{
	LocalizedText locaText = (LocalizedText)target;
	locaText.UpdateText();
	UnityEditor.EditorUtility.SetDirty(locaText);
}

This updates the “targetText” in the inspector and appears to be forcing a rebuild/redraw of the scene and game view, to also show the updated text. It also enabled the generic “Inspector changed” undo functionality. Everything works fine, but according to the docs, it shouldn’t.

The documentation states:

Marks target object as dirty. (Only suitable for non-scene objects).
NOTE: ‘‘Prior to Unity 5.3, this was
the primary method of marking objects
as dirty. From 5.3 onwards, with the
introduction of Multi-Scene Editing,
this function should no-longer be used
for modifying objects in scenes.
Instead, you should use
Undo.RecordObject prior to making
changes to the object. This will mark
the object’s scene as dirty and
provide an undo entry in the editor.’’

To me this says, that I should not be using the SetDirty function, and instead just record undo and everything would work, but it doesn’t. Is this a bug or am I misinterpreting my findings? Is SetDirty calling anything else, which I could also trigger myself with a more “correct” method?

The issue here is that the correct way to dirty a scene object is to use Undo.RecordObject(), as the documentation states. The problem is that this does not currently work as expected when you are modifying a prefab parent (e.g., an asset selected in the project view). In those cases you need to either call EditorUtility.SetDirty(), as you discovered, or PrefabUtility.MergeAllPrefabInstances(). A colleague and I actually just discovered this and brought it to the attention of the Asset Management team earlier this week, as we agree it should work the same in both cases. That said, using SerializedProperty to modify the text should theoretically work the same in both cases, which also obviates the need to do anything special for handling undo.