RaycastTargetとは?

RaycastTargetは、ImageTextなどのUIコンポーネントが持つプロパティです。これを有効にすると、そのUIオブジェクトがポインターのクリックやタップを受け取れるようになります。

Unityのクリック判定は以下の流れで行われます。

  1. EventSystemが毎フレームポインターの位置を監視する
  2. GraphicRaycasterがCanvas内のRaycastTargetが有効な全オブジェクトに対してレイキャストを行う
  3. ヒットしたオブジェクトに対してクリックイベントが発行される

つまり、RaycastTargetが有効なオブジェクトは毎フレーム判定処理の対象になります。

パフォーマンスへの影響

RaycastTargetが有効なオブジェクトが多いほど、GraphicRaycasterの処理負荷が増加します。

問題になりやすいのが、UnityのImageTextMeshProUGUIはデフォルトでRaycastTargetがオンになっている点です。

装飾目的で配置した背景画像やラベルテキストも、何も設定しなければすべてクリック判定の対象になってしまいます。

UIが複雑になるほどRaycastTargetが有効なオブジェクトが増え、パフォーマンスに影響が出やすくなります。

RaycastTargetをオフにすべき場面

クリックやタップに反応させる必要がないオブジェクトは、RaycastTargetをオフにします。

オフにすべき例:

  • 背景や枠線など装飾目的のImage
  • ボタンのラベルなど操作対象ではないTextTextMeshProUGUI
  • アイコンやイラストなど見た目だけのUI

オンのままにすべき例:

  • Buttonなど直接クリックを受け付けるUI
  • IPointerClickHandlerなどのイベントインターフェイスを実装したオブジェクト

InspectorのRaycast Targetチェックボックスのオン/オフで切り替えられます。

スクリプトから変更する場合は以下のように書きます。

using UnityEngine;
using UnityEngine.UI;

public class RaycastTargetSample : MonoBehaviour
{
    [SerializeField] private Image _image;

    private void Start()
    {
        // RaycastTargetをオフにする
        _image.raycastTarget = false;
    }
}

Blocks Raycastsとの違い

RaycastTargetと似た機能にCanvasGroupBlocks Raycastsがあります。2つの違いは制御の単位です。

プロパティ制御単位用途
RaycastTargetオブジェクト個別特定のUIのクリック判定を恒久的にオフにする
Blocks RaycastsCanvasGroup配下のグループ単位ローディング中など状況に応じてグループごと切り替える

装飾用の画像など最初からクリック判定が不要なものはRaycastTargetをオフに、状況に応じて操作を無効化したい場合はBlocks Raycastsを使うのが基本的な使い分けです。

エディタ拡張でRaycastTargetを一括確認する

シーンが大きくなると、RaycastTargetがオンになっているオブジェクトを手動で確認するのは手間がかかります。エディタ拡張を使ってシーン内の一覧を表示するツールを作ると便利です。

以下のスクリプトをEditorフォルダ内に保存すると、メニューバーから実行できます。

using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class RaycastTargetChecker : EditorWindow
{
    #region Fields

    private Vector2 _scrollPosition;

    #endregion

    [MenuItem("Tools/RaycastTarget Checker")]
    private static void Open()
    {
        GetWindow<RaycastTargetChecker>("RaycastTarget Checker");
    }

    private void OnGUI()
    {
        if (GUILayout.Button("シーンを検索"))
        {
            // フォーカスをシーンビューに移してリフレッシュ
            Repaint();
        }

        EditorGUILayout.Space();

        // シーン内のGraphicコンポーネントをすべて取得する
        var graphics = FindObjectsByType<Graphic>(FindObjectsSortMode.None);

        var count = 0;

        using (var scrollView = new EditorGUILayout.ScrollViewScope(_scrollPosition))
        {
            _scrollPosition = scrollView.scrollPosition;
            
            EditorGUI.BeginChangeCheck();

            foreach (var graphic in graphics)
            {
                using (new EditorGUILayout.HorizontalScope())
                {
                    // RaycastTargetの状態
                    graphic.raycastTarget = EditorGUILayout.ToggleLeft("", graphic.raycastTarget, GUILayout.Width(24));
                    
                    // オブジェクト名を表示する
                    EditorGUILayout.LabelField(graphic.gameObject.name, GUILayout.Width(200));

                    // コンポーネント名を表示する
                    EditorGUILayout.LabelField(graphic.GetType().Name, GUILayout.Width(160));

                    // クリックでオブジェクトを選択する
                    if (GUILayout.Button("選択", GUILayout.Width(60)))
                    {
                        Selection.activeGameObject = graphic.gameObject;
                        EditorGUIUtility.PingObject(graphic.gameObject);
                    }
                }
                
                if (graphic.raycastTarget)
                {
                    count++;
                }
            }

            if (EditorGUI.EndChangeCheck())
            {
                // 変更があったので、反映する
                var scene = SceneManager.GetActiveScene();
                EditorSceneManager.MarkSceneDirty(scene);
            }
        }

        EditorGUILayout.Space();
        EditorGUILayout.LabelField($"RaycastTarget が有効なオブジェクト: {count} 件");
    }
}

Tools > RaycastTarget Checkerからウィンドウを開くと、シーン内でRaycastTargetが有効なオブジェクトの一覧が表示されます。

チェックボックスを変更すると、該当するコンポーネントのRaycastTargetが実際に変更されます。

「選択」ボタンを押すとInspectorで該当オブジェクトを確認できます。

エディタ拡張の詳しい作り方はこちらの記事も参考にしてください。

まとめ

RaycastTargetは、UIオブジェクトがクリック判定を受け取るかどうかを制御するプロパティです。

  • デフォルトでオンになっているため、不要なオブジェクトはオフにすることでパフォーマンスを改善できる
  • クリックに反応する必要のない背景・装飾UIは積極的にオフにする
  • グループ単位で制御したい場合はCanvasGroupBlocks Raycastsを使う
  • エディタ拡張でシーン内の一覧を確認すると、見落としを防ぎやすい

UIが増えてきたタイミングで一度見直してみてください。