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

Unity脚本修改TextMeshProUGUI文本值的实现方法

Unity 无法修改TextMeshProUGUI文本值问题排查

问题背景

  • 开发玩家资料菜单填充功能时,模板对象下挂载有Image组件、Text (TMP) 子对象
  • 通过GameObject.FindGameObjectsWithTag查找所有带指定标签的模板对象,在循环中尝试将Json读取到的玩家数据赋值给对应文本,但始终无法修改TMP文本的显示值
  • Unity版本更新前,相同逻辑可正常修改原生UGUI Text组件内容,更新后TMP组件赋值无效
  • 经调试确认循环中可获取到TextMeshProUGUI类型对象,Json读取模块功能正常

问题原代码

using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class JSONReader : MonoBehaviour
{
    public TextAsset textJSON;
    public PlayerList myPlayerList = new PlayerList();
    public GameObject playerTemplate;
    public readonly string playerTemplateTag = "playerTemplate";
    
    
    //Player Model
    [System.Serializable]
    public class Player
    {
        public int id;
        public string name;
        public string imageLink;
    }
    
    //Array of Influencers
    [System.Serializable]
    public class PlayerList
    {
        public Player[] player;
    }
    
    // Start is called before the first frame update
    void Start()
    {
        myPlayerList = JsonUtility.FromJson<PlayerList>(textJSON.text);
        PopulatePlayerSelect();
        
    }
    
    private void PopulatePlayerSelect()
    {
    
        var buttonGameObjects = GameObject.FindGameObjectsWithTag(playerTemplateTag);
    
        foreach(GameObject playerTemplate in buttonGameObjects)
        {
    
            var image = playerTemplate.GetComponentsInChildren<Image>();
            var name =  playerTemplate.GetComponentsInChildren<TextMeshProUGUI>();
    
            Debug.Log(name);
        }
    }
}

问题原因

  1. 返回值类型理解错误:GetComponentsInChildren<TextMeshProUGUI>()返回的是TextMeshProUGUI[]数组类型,不是单个TMP组件实例,直接对数组变量操作,根本没有访问到具体组件的.text属性,自然无法修改显示内容
  2. 缺少数据映射逻辑:遍历模板对象时,没有将模板和Json中对应索引的玩家数据做绑定,即使拿到组件也没有可赋值的数据源
  3. 组件查找逻辑不严谨:GetComponentsInChildren会同时返回父物体挂载的同类型组件,如果模板自身挂了Image(比如按钮背景),会和头像Image混在同一个数组里,极易拿错组件;另外局部变量命名为name,和Unity内置的Object.name属性重名,容易引发逻辑混淆
  4. 不存在版本更新修改TMP文本属性名的情况,TMP组件的文本赋值属性一直是.text,和原生UGUI Text一致

修复方案

  1. 优先用transform.Find("子物体层级路径")精准定位名字文本、头像Image的所在对象,再获取对应组件,避免拿错
  2. 遍历模板时按索引匹配对应玩家数据,拿到单个TMP组件实例后,对其.text属性赋值
  3. 增加长度校验,避免模板数量和玩家数据数量不匹配引发的数组越界问题

修复后的填充方法参考:

private void PopulatePlayerSelect()
{
    var buttonGameObjects = GameObject.FindGameObjectsWithTag(playerTemplateTag);
    // 校验数据和模板数量匹配
    if (buttonGameObjects.Length != myPlayerList.player.Length)
    {
        Debug.LogError($"模板数量与玩家数据数量不匹配,模板数:{buttonGameObjects.Length},玩家数:{myPlayerList.player.Length}");
        return;
    }

    for (int i = 0; i < buttonGameObjects.Length; i++)
    {
        GameObject currentTemplate = buttonGameObjects[i];
        Player currentData = myPlayerList.player[i];

        // 替换括号内的路径为你自己项目中TMP文本、头像的实际子物体路径
        TextMeshProUGUI playerNameText = currentTemplate.transform.Find("NameText").GetComponent<TextMeshProUGUI>();
        Image playerAvatar = currentTemplate.transform.Find("AvatarIcon").GetComponent<Image>();

        // 赋值文本
        playerNameText.text = currentData.name;
        // 后续自行实现头像加载逻辑即可
    }
}

额外注意事项

  • 明确类型的变量尽量不要用var声明,尤其是组件查找的返回值,很容易因为隐式类型搞错对象结构
  • 如果是动态生成列表的场景,建议把模板初始设置为隐藏状态,所有数据赋值完成后再显示,避免出现空白闪烁
  • 不要用GetComponentsInChildren不加筛选地拿子物体组件,尤其是层级复杂的UI对象,精准查找的稳定性远高于批量获取

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:31:08