UGUI计算Text文字的宽度

UGUI计算Text组件里文字的宽度

1. 为什么要计算宽度

我碰到这个问题,是需要在Unity中利用UGUI来实现图文混排的功能,类似于网游中的聊天系统,文字和emoji表情可以一起发出去。我用的方式是将表情使用占位符表示,例如你吃饭了吗[微笑],其中这个[微笑]就是占位的。在解析中,将这个占位符解析出来,然后在该位置放上一张图片。那么获取这个图片的位置就很重要了。而要获取图片的位置,必然就需要计算前面的文字的宽度。

2.使用的组件

作为测试,canvas下只有一个text物体,并附加上Content Size Fitter组件,这个组件可以让文本框适应文字的大小。

3.代码部分

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class testlen : MonoBehaviour {
    public Text t ;
    private TextGenerator tg;
    private TextGenerationSettings settings;
    void Start () {
        tg = t.cachedTextGeneratorForLayout;
        settings = t.GetGenerationSettings(Vector2.zero);
        StartCoroutine(counter());
        t.text = "你好啊最近怎么样呢";
    }
    IEnumerator counter()
    {
        yield return new WaitForEndOfFrame();
        Debug.Log(tg.GetCharactersArray()[0].cursorPos);
        Debug.Log(tg.GetCharactersArray()[0].charWidth);
        Debug.Log(tg.GetPreferredWidth("你好",settings)/t.pixelsPerUnit);
    }
}

TextGenerator是文本生成器,文字的大部分功能都是由这个类实现的。在这个类中,提供了一些更底层的方法 ,让我们控制和文本相关的一些信息。所以在一开始,我就获取了text的生成器。用cachedTextGeneratorForLayout用这个属性获得,还有一个属性cachedTextGenerator,具体区别可参见官方文档,我也不是很清楚。TextGenerationSettings中包含了text设置相关的一些信息,例如字体大小、字体等。
这里有一个很重要的地方,写放上官方的文档

Details
Note that some RectTransform calculations are performed at the end of a frame, just before calculating UI vertices, in order to ensure that they are up to date with all the latest changes performed throughout the frame. This means that they haven’t yet been calculated for the first time in the Start callback and first Update callback.
You can work around this by creating a Start() callback and adding Canvas.ForceUpdateCanvases() method to it. This will force Canvas to be updated not at the end of the frame, but when that method is called.
See the Basic Layout page for a full introduction and overview of how to use the Rect Transform.

大致意思是说RectTransform组件的一些计算是在一帧的结束的地方,所以如何你在Start函数中需要进行一些计算,这可能就会出现一些问题,因为RectTransform组件的一些计算还没有进行,所以会出现一些错误的情况。但是可以使用Canvas.ForceUpdateCanvases()这个方法来强制更新,而不是在一帧的结束的地方 。为此我们来测试一下。

3.1在Start中直接使用一些计算信息

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class testlen : MonoBehaviour {
    public Text t ;
    public TextGenerator tg;
    TextGenerationSettings settings;
    // Use this for initialization
    void Start () {
        tg = t.cachedTextGeneratorForLayout;
        settings = t.GetGenerationSettings(Vector2.zero);
        //StartCoroutine(counter());
        t.text = "你好啊最近怎么样呢";
        Debug.Log(tg.GetCharactersArray()[0].cursorPos);
        Debug.Log(tg.GetCharactersArray()[0].charWidth);
        Debug.Log(tg.GetPreferredWidth("你好", settings) / t.pixelsPerUnit);
    }

结果会报错
报错

3.2调用Canvas.ForceUpdateCanvases()

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class testlen : MonoBehaviour {
    public Text t ;
    public TextGenerator tg;
    TextGenerationSettings settings;
    // Use this for initialization
    void Start () {
        tg = t.cachedTextGeneratorForLayout;
        settings = t.GetGenerationSettings(Vector2.zero);
        //StartCoroutine(counter());
        t.text = "你好啊最近怎么样呢";
        Canvas.ForceUpdateCanvases();
        Debug.Log(tg.GetCharactersArray()[0].cursorPos);
        Debug.Log(tg.GetCharactersArray()[0].charWidth);
        Debug.Log(tg.GetPreferredWidth("你好", settings) / t.pixelsPerUnit);
    }

成功
成功

4.总结

使用TextGenerator获取字符的长度,但是要注意调用的时间

猜你喜欢

转载自blog.csdn.net/wayway0554/article/details/80738071