以下の内容はhttps://www.karvan1230.com/entry/2021/01/19/221245より取得しました。


【Unity】TextMeshProでクリックされた文字列を取得する

緊急事態宣言

もはやコロナ慣れしてしまって緊急事態宣言だと言われても呑気に街へ出かけている皆さんこんにちは。私の住んでいる福岡県でも宣言が出されましたが、私は未だに在宅勤務にならず朝夕の通勤電車に乗っています。何故だろう?そりゃ罰則規定も考慮されますわ、ってかテレワーク推奨しない企業にも罰則つけて欲しい。

 

作り手として

微力ながらもゲームクリエータを志しているので、unityroomに投稿されているような個人製作のゲームを目にすると、純粋にゲームを楽しんだり、発想の意外さに驚嘆したりする前に、「このエフェクトは自作なのかな?アセットなのかな?」とか「この処理はどうやって作っているんだろう?」とか作り手としての目線でゲームを読み解こうとします。

無論、気になった部分全てを分析できるわけないのですが、「こうやっているかな?」とアレコレ夢想したり実際に作ってみたりするのは、勉強になるし楽しい作業です。

 

つい先日のunity1weekでも青木とと氏の「夢の中で、あなたと」というゲームについて非常に興味を惹かれました。

unityroom.com

テキスト形式の脱出ゲームとのことで、ゲーム画面には状況を説明するテキスト文だけが表示されます。

ユーザがテキスト文中のキーワードをクリックすると、そのキーワードが欄外に抽出されて後の場面でそれ文言をアイテムとして使用することができます。例えば 

「僕は机の引き出しからカッターナイフを取り出した」

という文章の"カッターナイフ"という部分をクリックすると、"カッターナイフ"というワードが取り出されて欄外に表示されます。その後に

「ガムテープで蓋をされた段ボールを見つけた」

という文章が表示されたら、先ほどの"カッターナイフ"を"段ボール"の上にドラッグすると

「カッターナイフで段ボールを開けると中にはドアの鍵が入っていた」

という文章が表示され、場面が展開していきます。ちょっと文章では伝わりにくいと思うので、上のリンクから是非プレイしてみてください。

 

とてもユニークなゲームシステムでunity1weekでも総合7位を勝ち取っているのですが、私的にはテキスト文中から一部ワードを切り出して欄外へ出す方法が非常に気になる。ってか私もアレやってみたい、作ってみたい!というわけで同じような事が出来ないか方法を探ってみました。

 

TextMeshProのLinkタグを利用する

TextMeshProではテキスト内にリッチテキストタグを使用することが出来ます。

 主にColorやSize等のタグでテキストのレイアウト、見た目を変更する際に利用されていると思うのですが、実はLinkタグを使ってハイパーリンクを張ることもできます

 ただし、ハイパーリンクを利用するにはスクリプトでクリックされた箇所のハイパーリンク(URL)を取得すしてApplication.OpenURL等でリンク先を表示する、という処理を作りこむ必要があります。

using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;

[RequireComponent( typeof( TextMeshProUGUI ) )]
public class Example : MonoBehaviour, IPointerClickHandler
{
    public void OnPointerClick( PointerEventData e )
    {
        TextMeshProUGUI text = GetComponent<TextMeshProUGUI>();
        Vector3 pos = Input.mousePosition;
        Camera camera = canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera;
        int index = TMP_TextUtilities.FindIntersectingLink( text, pos, camera );

        if ( index == -1 ) return;

        // リンクを取得
        TMP_LinkInfo linkInfo = text.textInfo.linkInfo[ index ];
        string url = linkInfo.GetLinkID();
        
        // リンク先を表示
        Application.OpenURL( url );
    }
}

上記のスクリプトをTextMeshProのオブジェクトにアタッチして使用します。

注意事項としてTextMeshProがあるCanvasはRenderModeが「Screen Space - Camera」か「World Space」である必要があります

 

例えば

Clickで<link="https://www.karvan1230.com/">リンク</link>をとりだす

という文章について上記のスクリプトを利用すると、

f:id:Karvan:20210119215811g:plain

Linkタグで囲まれたテキスト部分(”リンク”)をクリックするとLinkタグに設定されたURLを取得することができます。

 

Linkタグは一文中に幾つも設定できるので、例えば以下のように

Clickで<link="https://www.karvan1230.com/">リンク</link>をとりだす。わからないので<link="https://www.google.co.jp/">Google</link>でしらべる。

と、複数のLinkタグが設定されている場合でも、それぞれに応じたURLを取得することができます。

f:id:Karvan:20210119220043g:plain

 つまり、これを利用すればテキスト文中からクリックされた箇所のワードを取り出して後の処理に利用することも可能だ、と言う事です。

 

クリック位置を取得する

先ほどの処理でクリックした文言を判定することが出来るので、後はそのワードを欄外へ移動すれば良いわけです。

移動用のTextMeshProをあらかじめ用意しておいて、それをクリックした位置から欄外へ移動させます。

 

uGUIでクリックした位置はRectTransformUtilityのScreenPointToLocalPointInRectangleを使うことでCanvas内のローカル位置を取得することができます。

 先ほどのOnPointerClick関数内に以下のコードを追加します。

 // クリック位置に対応するRectTransformのlocalPositionを計算する
 RectTransform rectTransform = canvas.GetComponent<RectTransform>
 var localPoint = Vector2.zero;
 RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, pos, camera, out localPoint);

取得したlocalPointを移動用のTextMeshPro(のRectTranform)のlocalPositionに設定してDOTween等で移動を行います。

 

f:id:Karvan:20210119220604g:plain

こんな感じ。ちなみに上の動画ではクリックされたLinkタブの箇所にColorタブを追加して色を変更する処理も行っています。

 

IPointerClickHandlerとか今回始めて知りました。やっぱり賢者の方が作ったゲームは色々と勉強になりますね。

 




以上の内容はhttps://www.karvan1230.com/entry/2021/01/19/221245より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14