UnityUGUI重写Text组件Set访问器,适配新版TMP

【Unity】UGUI新版TMP和旧版Text组件的适配器

2017年Unity就已经收购并内置了文本插件TextMeshPro,简称TMP。可是还有大部分遗留项目广泛依赖原本的Text组件,为了能让旧有项目适配使用TMP,不得不做一些适配工作。

从Unity的官方手册上可以看到,TMP是官方公认Text组件的完美替代,如果使用较新版本的Unity,可以发现旧版Text已经被归类为遗产。旧版Text的另一种说法也就是Legacy Text,因此它大概率会被慢慢弃用,不会有后续的更新维护了。

不过至少就目前而言,真实工作时还是会遇到很多无法或不愿弃用旧版Text组件的情况,这时候一个简单的适配逻辑就有了作用。

重写部分实际很少,大部分是旧版Text源码。

TextAdapterTMP.cs 代码如下:

using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class TextAdapterTMP : Text
{
    // 注意区分 TextMeshPro 和 TextMeshProUGUI
    [SerializeField] private TextMeshProUGUI _textShow;

    public override string text
    {
        get
        {
            return m_Text;
        }
        set
        {
            if(string.IsNullOrEmpty(value))
            {
                if (string.IsNullOrEmpty(m_Text))
                    return;
                m_Text = "";
                SetVerticesDirty();
            }
            else if(m_Text != value)
            {
                m_Text = value;
                SetVerticesDirty();
                SetLayoutDirty();

                // 只重写了一个赋值
                _textShow.text = value; 
            }
        }
    }

    // 增加几个生命周期的及时响应,
    // 实际没什么应用情景,
    // 现有问题无法完美解决
    protected override void Awake()
    {
        base.Awake();
        HideOldShowNew();
    }
    protected override void OnEnable()
    {
        base.OnEnable();
        HideOldShowNew();
    }
    protected override void Start()
    {
        base.Start();
        HideOldShowNew();
    }

    // 隐藏旧版Text显示,新版TMP文本赋值
    private void HideOldShowNew()
    {
        _textShow.text = text;
        color = Color.clear;
    }

    // 测试一下逻辑是否正确
    private void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            text = "测试<sprite=0>测试<sprite=1>一二三四五<sprite=5>";
        }
    }
}

另外,旧版 Text 的 Inspector 逻辑也被封死在一个 TextEditor 类中,需要在 Editor 文件夹下创建 TextAdapterTMP_Editor.cs。重写部分编辑器逻辑才能在 Inspector 中便利地拖动绑定 TMP 对象。代码如下:

using UnityEditor;

[CustomEditor(typeof(TextAdapterTMP), true)]
[CanEditMultipleObjects]
public class TextAdapterTMP_Editor : UnityEditor.UI.TextEditor 
{
    private SerializedProperty _textShow;

    // TextEditor 和 UnityEditor.UI.TextEditor 是两个类,要注意区分
    // 如果没有可重写的方法,注意检查是否继承了错误的 TextEditor 类
    protected override void OnEnable()
    {
        base.OnEnable();
        _textShow = serializedObject.FindProperty("_textShow");
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        EditorGUILayout.Space();
        serializedObject.Update();
        EditorGUILayout.PropertyField(_textShow);
        serializedObject.ApplyModifiedProperties();
    }
}

能够使用 TMP 的话,很多 Text 的坑就都可以避免了。类似图文混排等功能也变得极易实现。
新旧版Text组件适配测试

更优的方案,当然还是更新底层逻辑支持TMP,虽然很多时候,这并不现实。最后记录两篇 TMP 的使用参考:

[参考文档] https://zhuanlan.zhihu.com/p/457041220
[参考文档] https://zhuanlan.zhihu.com/p/458678835