본문 바로가기

공부/유니티

[Unity] 툴팁 만들기 - part3. link 태그로 텍스트에 툴팁 넣기

게임 중에 특정 텍스트에 마우스를 올리면 툴팁이 보이는 기능이 있었다.

처음에는 TooltipTrigger를 가진 빈 오브젝트의 위치를 특정 텍스트에 맞춰 옮겨 툴팁을 구현한 줄 알았다.

하지만, 구글링을 하다보니 link 리치 텍스트 태그를 사용하여 특정 텍스트에 툴팁을 적용할 수 있다는 사실을 깨닫게 되었다.

이번 글에서는 link 리치 텍스트 태그에 대해 공부한 내용을 정리해보고자 한다.

예시 이미지 (게임명: 에픽세븐)


리치 텍스트 태그는 TextMeshPro에서 텍스트에 스타일을 입히기 위해 사용하는 마크업 태그이다.

그 중, link 태그는 하이퍼링크처럼 사용하라고 제공된 태그로 스크립트를 통해 link 태그의 ID와 감싸진 Text에 접근하여 다양한 로직을 실행시킬 수 있다.

<link="ID">Text</link>

 

스크립트에서 link 태그에 접근하는 방법으로는 TMP_TextUtilities 클래스에서 찾을 수 있다.

아래 이미지를 보면 정말 다양한 메서드들이 있지만 나는 FindIntersectingLink와 IsIntersectingRectTransform를 사용하였다.

FindIntersectingLink는 현재 마우스의 위치가 link 태그로 감싸진 텍스트 위에 있다면 몇 번째 link 태그인지 반환한다.

link 위에 마우스가 없다면 -1을 반환한다.

여기서 문제는 FindIntersectingLink는 텍스트 내부의 모든 링크 정보를 순회하고, 문자들의 위치, 크기, visible 여부 등을 계산해서 충돌을 체크한다는 것이다. 이는 상당한 비용이 들어간다.

이를 해결하기 위해, IsIntersectingRectTransform를 사용할 수 있는데, 이 메서드는 단순히 텍스트의 RectTransform 내부에 마우스가 존재하는지 판단하는 메서드이기 때문이다.

매 프레임 실행되야 하기에 최적화를 위해, IsIntersectingRectTransform로 선체크를 한 후에, FindIntersectingLink로 선택된 링크를 받는 방식으로 사용하였다.

※ Camera 매개변수는 3D 환경에 있는 텍스트에 사용할 경우 넣어주어야 한다. 2D에서는 Null을 넣어주어도 된다.

 

private void LateUpdate()
{
    Vector3 mousePos = Input.mousePosition;

    // 변경 없으면 아무것도 하지 않음
    if (_lastMousePosition == mousePos && _cachedLinkIndex == -1)
        return;

    _lastMousePosition = mousePos;

    // 마우스가 텍스트 영역 안에 없다면
    if (TMP_TextUtilities.IsIntersectingRectTransform(_text.rectTransform, mousePos, null) == false)
    {
        ResetTooltip();
        return;
    }

    // 몇 번째 link태그인지 구하기
    int linkIndex = TMP_TextUtilities.FindIntersectingLink(_text, mousePos, null);

    // 링크를 벗어난 경우
    if (linkIndex != _cachedLinkIndex)
    {
        ResetTooltip();

        // 마우스가 링크 위에 없을 경우
        if (linkIndex == -1) return;

        _cachedLinkIndex = linkIndex;

        // 툴팁 처리
        ShowTooltip(linkIndex);
    }
}

 

link 태그로 감싸진 텍스트 위에 마우스가 있다면 ShowTooltip 메서드를 호출하도록 하였다.

ShowTooltip에서는 미리 정해둔 툴팁의 linkName과 link태그의 id를 맞춰 일치하는 TooltipData를 적용해주었다.

link태그의 id를 불러오기 위해 TMP_LinkInfo 구조체의 GetLinkID를 사용하였다.

private void ShowTooltip(int linkIndex)
{
    if (_trigger == null) return;

    string linkID = _text.textInfo.linkInfo[linkIndex].GetLinkID();
    LinkTooltip linkTooltip = _template.linkTooptips.Find(x => x.linkName == linkID);

    if (linkTooltip == null) return;

    if (linkTooltip.data.IsInitializeData() == false) linkTooltip.data.InitializeData();

    _trigger.tooltipStyle = linkTooltip.style;
    _trigger.tooltipData = linkTooltip.data;
    _trigger.StartHover();
}

 

미리 지정할 툴팁은 TooltipTemplate에서 TooltipTrigger를 구현할 때 처럼 Tooltip Style을 넣어서 데이터를 수정할 수 있게 구현하였다.


결과