본문 바로가기
유니티

unity TMP_TextUtilities 클릭한 글자 가져오기

by 유니티세상 2026. 4. 23.
반응형

 

https://docs.unity3d.com/Packages/com.unity.textmeshpro@1.2/api/TMPro.TMP_TextUtilities.html

 


1. 어떤 상황에서 쓰는 클래스인가?

보통 이런 때 씁니다.

  1. 텍스트 클릭 판정
    • “어떤 글자를 클릭했는지”
    • “어떤 단어를 눌렀는지”
    • “링크를 눌렀는지”
  2. 텍스트 커서 위치 계산
    • 간단한 채팅 입력기
    • 커스텀 텍스트 에디터
    • 클릭한 위치에 caret 넣기
  3. 텍스트 UI 위 마우스 판정
    • 마우스가 TMP 텍스트 영역 위에 있는지 검사
    • 툴팁 표시 여부 결정

공식 문서상 FindIntersectingCharacter는 특정 위치에서 문자 인덱스를, FindIntersectingWord는 단어 인덱스를, FindIntersectingLink는 링크 인덱스를 반환하도록 되어 있습니다. GetCursorIndexFromPosition은 커서에 가장 가까운 문자 origin 기준 인덱스를 반환합니다. (Unity Documentation)


2. 가장 많이 쓰는 기본 세팅

using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

public class TmpUtilityBasicSetup : MonoBehaviour, IPointerClickHandler
{
    [SerializeField] private TMP_Text targetText;
    [SerializeField] private Camera targetCamera;

    public void OnPointerClick(PointerEventData eventData)
    {
        Vector3 clickPosition = eventData.position;

        int characterIndex = TMP_TextUtilities.FindIntersectingCharacter(
            targetText,
            clickPosition,
            targetCamera,
            true
        );

        Debug.Log("Character Index: " + characterIndex);
    }
}

설명

  • targetText 검사할 TextMeshPro 컴포넌트입니다.
  • clickPosition 마우스 클릭 좌표입니다.
  • targetCamera 문서를 보면 ScreenSpace Overlay면 null, ScreenSpace Camera / World Space면 해당 카메라를 넣으라고 되어 있습니다. (Unity Documentation)
  • true visibleOnly 옵션입니다. 보이는 글자만 대상으로 검사합니다. (Unity Documentation)

3. 활용 예시 1 — 클릭한 글자 알아내기

이건 가장 대표적인 예시입니다.

using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

public class TmpCharacterClickExample : MonoBehaviour, IPointerClickHandler
{
    [SerializeField] private TMP_Text targetText;
    [SerializeField] private Camera targetCamera;

    public void OnPointerClick(PointerEventData eventData)
    {
        int characterIndex = TMP_TextUtilities.FindIntersectingCharacter(
            targetText,
            eventData.position,
            targetCamera,
            true
        );

        if (characterIndex == -1)
        {
            Debug.Log("글자를 클릭하지 않았습니다.");
            return;
        }

        TMP_CharacterInfo characterInfo = targetText.textInfo.characterInfo[characterIndex];
        Debug.Log("클릭한 글자: " + characterInfo.character);
    }
}

어디에 쓰나?

  • 닉네임 한 글자씩 효과 주기
  • 텍스트 타자 게임
  • 특정 문자 클릭 시 강조

핵심 포인트

FindIntersectingCharacter는 해당 위치에 걸친 글자 인덱스를 반환합니다. 글자가 없으면 보통 -1로 처리합니다. 이 메서드는 문서에 “given position의 character index 반환”으로 설명되어 있습니다. (Unity Documentation)


4. 활용 예시 2 — 클릭한 단어 알아내기

단어 단위로 상호작용할 때 유용합니다.

using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

public class TmpWordClickExample : MonoBehaviour, IPointerClickHandler
{
    [SerializeField] private TMP_Text targetText;
    [SerializeField] private Camera targetCamera;

    public void OnPointerClick(PointerEventData eventData)
    {
        int wordIndex = TMP_TextUtilities.FindIntersectingWord(
            targetText,
            eventData.position,
            targetCamera
        );

        if (wordIndex == -1)
        {
            Debug.Log("단어를 클릭하지 않았습니다.");
            return;
        }

        TMP_WordInfo wordInfo = targetText.textInfo.wordInfo[wordIndex];
        string clickedWord = wordInfo.GetWord();

        Debug.Log("클릭한 단어: " + clickedWord);
    }
}

어디에 쓰나?

  • 단어 학습 앱
  • 텍스트 내 키워드 선택
  • 대사문에서 단어 툴팁

문서에 따르면 FindIntersectingWord는 지정 위치에 해당하는 word index를 반환합니다. (Unity Documentation)


5. 활용 예시 3 — 링크 클릭 처리

TMP 텍스트 안에 <link> 태그를 넣어두고 링크별 동작을 처리할 수 있습니다.

TMP 텍스트 예시

이용약관은 <link="terms">여기</link>를 누르세요.
개인정보처리방침은 <link="privacy">여기</link>를 누르세요.

스크립트 예시

using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

public class TmpLinkClickExample : MonoBehaviour, IPointerClickHandler
{
    [SerializeField] private TMP_Text targetText;
    [SerializeField] private Camera targetCamera;

    public void OnPointerClick(PointerEventData eventData)
    {
        int linkIndex = TMP_TextUtilities.FindIntersectingLink(
            targetText,
            eventData.position,
            targetCamera
        );

        if (linkIndex == -1)
        {
            Debug.Log("링크를 클릭하지 않았습니다.");
            return;
        }

        TMP_LinkInfo linkInfo = targetText.textInfo.linkInfo[linkIndex];
        string linkId = linkInfo.GetLinkID();

        Debug.Log("클릭한 링크 ID: " + linkId);

        if (linkId == "terms")
        {
            Debug.Log("이용약관 창 열기");
        }
        else if (linkId == "privacy")
        {
            Debug.Log("개인정보처리방침 창 열기");
        }
    }
}

어디에 쓰나?

  • 이용약관 / 개인정보처리방침
  • 채팅창 하이퍼링크
  • 퀘스트 텍스트의 NPC 이름 클릭

문서상 FindIntersectingLink는 주어진 위치의 link index를 반환합니다. (Unity Documentation)


6. 활용 예시 4 — 마우스가 어느 줄 위에 있는지 알아내기

여러 줄 텍스트에서 줄 단위 강조를 하고 싶을 때 씁니다.

using TMPro;
using UnityEngine;

public class TmpLineHoverExample : MonoBehaviour
{
    [SerializeField] private TMP_Text targetText;
    [SerializeField] private Camera targetCamera;

    private void Update()
    {
        int lineIndex = TMP_TextUtilities.FindIntersectingLine(
            targetText,
            Input.mousePosition,
            targetCamera
        );

        if (lineIndex != -1)
        {
            Debug.Log("현재 마우스가 올라간 줄 인덱스: " + lineIndex);
        }
    }
}

문서에는 FindIntersectingLine이 position과 교차하는 line을 반환한다고 나와 있습니다. FindNearestLine은 교차가 아니더라도 가장 가까운 줄을 찾는 용도입니다. (Unity Documentation)


7. 활용 예시 5 — 클릭 위치로 커서 인덱스 구하기

간단한 텍스트 입력기나 커스텀 에디터를 만들 때 핵심입니다.

using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

public class TmpCursorIndexExample : MonoBehaviour, IPointerClickHandler
{
    [SerializeField] private TMP_Text targetText;
    [SerializeField] private Camera targetCamera;

    public void OnPointerClick(PointerEventData eventData)
    {
        CaretPosition caretPosition;
        int cursorIndex = TMP_TextUtilities.GetCursorIndexFromPosition(
            targetText,
            eventData.position,
            targetCamera,
            out caretPosition
        );

        Debug.Log("Cursor Index: " + cursorIndex);
        Debug.Log("Caret Position: " + caretPosition);
    }
}

이게 왜 useful 한가?

예를 들어:

  • "HelloWorld" 텍스트가 있고
  • 사용자가 Hello|World 위치를 클릭했다면
  • 그 위치에 맞는 인덱스를 구해서 caret를 둘 수 있습니다.

문서상 GetCursorIndexFromPosition은 cursor에 가장 가까운 character origin index를 반환하고, 오버로드 버전은 out CaretPosition도 제공합니다. (Unity Documentation)


8. 활용 예시 6 — 텍스트 영역 위에 마우스가 있는지 검사

문자까지는 필요 없고, “그 텍스트 UI 위에만 있으면 된다”는 경우가 있습니다.

using TMPro;
using UnityEngine;

public class TmpRectIntersectionExample : MonoBehaviour
{
    [SerializeField] private TMP_Text targetText;
    [SerializeField] private Camera targetCamera;

    private void Update()
    {
        RectTransform rectTransform = targetText.rectTransform;

        bool isMouseOver = TMP_TextUtilities.IsIntersectingRectTransform(
            rectTransform,
            Input.mousePosition,
            targetCamera
        );

        if (isMouseOver)
        {
            Debug.Log("마우스가 텍스트 영역 위에 있습니다.");
        }
    }
}

문서상 IsIntersectingRectTransform은 position이 RectTransform과 교차하는지를 판단하는 함수입니다. (Unity Documentation)


9. 활용 예시 7 — 월드 좌표로 변환해서 툴팁 띄우기

ScreenPointToWorldPointInRectangle은 화면 좌표를 Rect 기준 월드 좌표로 바꾸는 메서드입니다. 문서에 “ScreenPoint를 Rectangle에 정렬된 WorldPoint로 변환”하는 용도라고 나옵니다. (Unity Documentation)

using TMPro;
using UnityEngine;

public class TmpTooltipPositionExample : MonoBehaviour
{
    [SerializeField] private RectTransform targetRectTransform;
    [SerializeField] private Camera targetCamera;
    [SerializeField] private RectTransform tooltipRectTransform;

    private void Update()
    {
        Vector3 worldPoint;
        bool isSuccess = TMP_TextUtilities.ScreenPointToWorldPointInRectangle(
            targetRectTransform,
            Input.mousePosition,
            targetCamera,
            out worldPoint
        );

        if (isSuccess)
        {
            tooltipRectTransform.position = worldPoint;
        }
    }
}

어디에 쓰나?

  • 단어 위 툴팁
  • 링크 hover UI
  • 문장 강조 포인터

10. 실무에서 가장 자주 쓰는 조합

실무에서는 보통 아래 조합이 많습니다.

1) 링크 클릭 UI

  • FindIntersectingLink
  • textInfo.linkInfo[linkIndex]

2) 단어 툴팁

  • FindIntersectingWord
  • textInfo.wordInfo[wordIndex]

3) 커스텀 입력기

  • GetCursorIndexFromPosition

4) hover 판정

  • IsIntersectingRectTransform
  • 필요하면 FindNearestCharacter

공식 문서에도 FindNearestCharacter, FindNearestWord, FindNearestLink, FindNearestLine처럼 “교차”가 아니라 가장 가까운 대상을 찾는 메서드들이 따로 제공됩니다. (Unity Documentation)


11. 주의할 점

1. Camera를 잘 넣어야 한다

문서 기준으로:

  • Screen Space Overlay → camera = null
  • Screen Space Camera / World Space → 해당 카메라 전달 (Unity Documentation)

이걸 틀리면 클릭 판정이 이상하게 나올 수 있습니다.

2. textInfo는 텍스트가 갱신된 뒤 기준이다

텍스트를 바꾼 직후 바로 textInfo를 읽을 때는 경우에 따라 갱신 타이밍을 확인해야 합니다.

targetText.ForceMeshUpdate();

3. -1 체크를 꼭 해야 한다

문자/단어/링크가 없으면 인덱스가 유효하지 않을 수 있으니 바로 배열 접근하면 위험합니다.


통합 예제

using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

public class TmpTextUtilitiesAllInOneExample : MonoBehaviour, IPointerClickHandler
{
    [SerializeField] private TMP_Text targetText;
    [SerializeField] private Camera targetCamera;

    public void OnPointerClick(PointerEventData eventData)
    {
        Vector3 clickPosition = eventData.position;

        int linkIndex = TMP_TextUtilities.FindIntersectingLink(targetText, clickPosition, targetCamera);
        if (linkIndex != -1)
        {
            TMP_LinkInfo linkInfo = targetText.textInfo.linkInfo[linkIndex];
            Debug.Log("링크 클릭: " + linkInfo.GetLinkID());
            return;
        }

        int wordIndex = TMP_TextUtilities.FindIntersectingWord(targetText, clickPosition, targetCamera);
        if (wordIndex != -1)
        {
            TMP_WordInfo wordInfo = targetText.textInfo.wordInfo[wordIndex];
            Debug.Log("단어 클릭: " + wordInfo.GetWord());
            return;
        }

        int characterIndex = TMP_TextUtilities.FindIntersectingCharacter(targetText, clickPosition, targetCamera, true);
        if (characterIndex != -1)
        {
            TMP_CharacterInfo characterInfo = targetText.textInfo.characterInfo[characterIndex];
            Debug.Log("글자 클릭: " + characterInfo.character);
            return;
        }

        Debug.Log("텍스트의 유효한 문자/단어/링크를 클릭하지 않았습니다.");
    }
}

요약

TMP_TextUtilities는 쉽게 말하면:

  • 텍스트를 클릭했을 때
  • 어느 글자/단어/링크/줄인지 찾아주는 도구 모음입니다. (Unity Documentation)

가장 실전적인 메서드는 보통 아래입니다.

  • FindIntersectingCharacter
  • FindIntersectingWord
  • FindIntersectingLink
  • GetCursorIndexFromPosition
  • IsIntersectingRectTransform (Unity Documentation)

 

반응형