본문 바로가기

개발/Unity, C#

Unity UGUI Text에서 특정 단어의 위치 찾기

 

여기저기 뒤져봤는데 바로 가져다 쓸만한 정보가 없어서

 

혼자 Text 클래스 내용 보면서 만든 소스

 

포지션은 첫 글자 좌상단 기준이고

 

Anchor는 해당 Text의 Anchor와 동일하게 해야 쓰기 쉬울듯함

(사실 비율 계산해서 정확하게 만들어 줄 수도 있지만 각자 알아서 쓰는 것이 더 좋을듯함)

 

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public static class TextUtil
{
    public static bool GetWordRectInText(this Text textUI, out Rect rect, string word)
    {
        rect = new Rect();
        if (string.IsNullOrEmpty(textUI.text) || string.IsNullOrEmpty(word) || !textUI.text.Contains(word))
        {
            return false;
        }

        Canvas.ForceUpdateCanvases();

        TextGenerator textGenerator = textUI.cachedTextGenerator;
        if (textGenerator.characterCount == 0)
        {
            textGenerator = textUI.cachedTextGeneratorForLayout;
        }

        if (textGenerator.characterCount == 0 || textGenerator.lineCount == 0)
        {
            return false;
        }

        List<UILineInfo> lines = textGenerator.lines as List<UILineInfo>;
        List<UICharInfo> characters = textGenerator.characters as List<UICharInfo>;

        int startIndex = textUI.text.IndexOf(word);
        UILineInfo lineInfo = new UILineInfo();
        for (int i = textGenerator.lineCount - 1; i >= 0; i--)
        {
            if (lines != null && lines[i].startCharIdx <= startIndex)
            {
                lineInfo = lines[i];
                break;
            }
        }

        if (lines != null && characters != null)
        {
            var anchoredPosition = textUI.rectTransform.anchoredPosition;

            var screenRatio = 720f / Screen.height; // 기준해상도

            rect.x = characters[startIndex].cursorPos.x * screenRatio + anchoredPosition.x;

            var temp = anchoredPosition.y / screenRatio;
            var yRatio = (float)Math.Round(temp, MidpointRounding.AwayFromZero); // 반올림 해줘야함
            rect.y = lineInfo.topY + yRatio;

            for (var index = startIndex; index < startIndex + word.Length; index++)
            {
                var info = characters[index];
                rect.width += info.charWidth * screenRatio;
            }

            rect.height = lineInfo.height * screenRatio;
        }

        return true;
    }
}

 

 

테스트 소스

using UnityEngine;
using UnityEngine.UI;

public class Test : MonoBehaviour
{
    public Text text;
    public Image img;

    void Start()
    {
        if (text.GetRectInText(out var rect, "강조") == true)
        {
            img.rectTransform.anchorMin = text.rectTransform.anchorMin;
            img.rectTransform.anchorMax = text.rectTransform.anchorMax;
            img.rectTransform.pivot = new Vector2(0f, 1f);

            img.rectTransform.anchoredPosition = new Vector2(rect.x, rect.y);
            img.rectTransform.sizeDelta = new Vector2(rect.width, rect.height);
        }

    }
}

 

 

결과