原カバンは鞄のお店ではありません。

Unityを使ったゲーム制作のあれこれを綴っていきます。

【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とか今回始めて知りました。やっぱり賢者の方が作ったゲームは色々と勉強になりますね。

 

◇プライバシーポリシー

●個人情報の利用目的

当ブログでは、メールでのお問い合わせ、メールマガジンへの登録などの際に、名前(ハンドルネーム)、メールアドレス等の個人情報をご登録いただく場合がございます。

これらの個人情報は質問に対する回答や必要な情報を電子メールなどをでご連絡する場合に利用させていただくものであり、個人情報をご提供いただく際の目的以外では利用いたしません。

●個人情報の第三者への開示

当サイトでは、個人情報は適切に管理し、以下に該当する場合を除いて第三者に開示することはありません。

・本人のご了解がある場合
・法令等への協力のため、開示が必要となる場合

個人情報の開示、訂正、追加、削除、利用停止
ご本人からの個人データの開示、訂正、追加、削除、利用停止のご希望の場合には、ご本人であることを確認させていただいた上、速やかに対応させていただきます。

アクセス解析ツールについて

当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。

このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。このトラフィックデータは匿名で収集されており、個人を特定するものではありません。
この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。

●免責事項

当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。

当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。

当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

●プライバシーポリシーの変更について

当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。