【Cocos Creator】アタッチするだけ!HitboxVisualizer (当たり判定可視化)の実装方法【TypeScript】

Godot 4ゲーム制作 実践ドリル 100本ノック

新品価格
¥1,250から
(2025/12/13 21:27時点)

Godot4& GDScriptではじめる 2Dゲーム開発レシピ

新品価格
¥590から
(2025/12/13 21:46時点)

Unity 6 C#スクリプト 100本ノック

新品価格
¥1,230から
(2025/12/29 10:28時点)

Cocos Creator100本ノックTypeScriptで書く!

新品価格
¥1,250から
(2025/12/29 10:32時点)

【Cocos Creator 3.8】HitboxVisualizerの実装:アタッチするだけでCollisionShapeのデバッグ表示を切り替える汎用スクリプト

このガイドでは、PhysicsCollider / Collider2D が持つ衝突形状(CollisionShape)を、ゲーム実行中にいつでも ON/OFF できる汎用コンポーネント「HitboxVisualizer」を実装します。

ノードにこのコンポーネントをアタッチするだけで、デバッグ用の当たり判定可視化(Visible Collision)をボタン感覚で切り替えできるようになり、物理挙動や当たり判定の調整が格段にやりやすくなります。


コンポーネントの設計方針

実現したい機能

  • 対象ノードに付いている 3D物理PhysicsCollider)または 2D物理Collider2D)のデバッグ表示をON/OFF する。
  • 外部のGameManagerやシングルトンに一切依存せず、このコンポーネント単体で完結する。
  • インスペクタから
    • 起動時に可視化するかどうか
    • 2D/3Dのどちらを対象にするか
    • キー入力でトグルするかどうか
    • トグル用のキーコード

    を設定できるようにする。

  • 必須コンポーネント(Collider / Collider2D)が無い場合は、エラーログを出して安全に無効化する。

デバッグ可視化の考え方

Cocos Creator 3.8 では、物理デバッグ描画は 物理システム単位(2D/3Dそれぞれ)で有効化する仕組みです。
本コンポーネントは、この仕組みを利用しつつ、以下のように動作します。

  • 2D物理
    • PhysicsSystem2D.instance.debugDrawFlags を操作してデバッグ描画をON/OFF。
    • 対象ノードに Collider2D が無い場合はエラーを出す。
  • 3D物理
    • PhysicsSystem.instance.debugDrawFlags を操作してデバッグ描画をON/OFF。
    • 対象ノードに PhysicsCollider(例: BoxCollider など)が無い場合はエラーを出す。

デバッグ描画は「システム全体」に対して有効化されますが、このコンポーネントが1つでもONにすれば表示され、すべてOFFにすれば非表示という使い方を想定します。
(1シーンに1つ配置する運用をおすすめします。複数配置しても動きますが、最後に操作したものの状態がシステムに反映されます。)

インスペクタで設定可能なプロパティ

HitboxVisualizer に用意する @property は次の通りです。

  • use2DPhysics (boolean)
    • 説明: 2D物理(Collider2D)を対象にするかどうか
    • true: Collider2D を探し、PhysicsSystem2D のデバッグ描画を操作。
    • false: 3D物理(PhysicsCollider)を対象にする。
  • enableOnStart (boolean)
    • 説明: ゲーム開始時(start())に デバッグ表示を有効化するか
    • true: シーン開始と同時に当たり判定が可視化される。
    • false: 初期状態は非表示。必要に応じて後述のキー入力やAPIでONにする。
  • allowKeyToggle (boolean)
    • 説明: キー入力でON/OFFを切り替えられるようにするか
    • true: 指定キーを押すたびに可視化状態をトグル。
    • false: キー操作では切り替えない(スクリプトから setVisible などで制御)。
  • toggleKeyCode (KeyCode)
    • 説明: デバッグ表示をトグルするためのキー。
    • デフォルト: KeyCode.KEY_H(Hitboxの H)。
    • 例: KeyCode.KEY_D など、お好みのキーに変更可能。
  • logDetail (boolean)
    • 説明: トグル時に 現在の状態や対象のCollider情報をログ出力するか
    • true: ON/OFF時に console.log で詳細を出力。
    • false: エラー以外のログを抑制。

この設計により、外部スクリプトに依存せず、インスペクタだけで完結した設定・制御が可能になります。


TypeScriptコードの実装

以下が完成した HitboxVisualizer コンポーネントの全コードです。


import {
    _decorator,
    Component,
    Node,
    warn,
    error,
    input,
    Input,
    EventKeyboard,
    KeyCode,
} from 'cc';
import { PhysicsSystem, EPhysicsDrawFlags, PhysicsCollider } from 'cc';
import { PhysicsSystem2D, EPhysics2DDrawFlags, Collider2D } from 'cc';

const { ccclass, property } = _decorator;

/**
 * HitboxVisualizer
 *
 * 対象ノードに付いている Collider / Collider2D のデバッグ表示を
 * 実行中に ON/OFF できる汎用コンポーネント。
 *
 * 外部の GameManager などには一切依存せず、このスクリプト単体で完結する。
 */
@ccclass('HitboxVisualizer')
export class HitboxVisualizer extends Component {

    @property({
        tooltip: '2D物理(Collider2D)を対象にするかどうか。\n' +
            'ON: PhysicsSystem2D のデバッグ描画を操作します。\n' +
            'OFF: 3D物理(PhysicsCollider)を対象にします。'
    })
    public use2DPhysics: boolean = true;

    @property({
        tooltip: 'ゲーム開始時(start)に当たり判定のデバッグ表示を有効化するかどうか。'
    })
    public enableOnStart: boolean = true;

    @property({
        tooltip: 'キー入力でデバッグ表示をトグルできるようにするかどうか。'
    })
    public allowKeyToggle: boolean = true;

    @property({
        tooltip: 'デバッグ表示の ON/OFF を切り替えるキー。\n' +
            'allowKeyToggle が ON のときのみ有効です。'
    })
    public toggleKeyCode: KeyCode = KeyCode.KEY_H;

    @property({
        tooltip: 'ON/OFF 切り替え時に詳細ログを出力するかどうか。'
    })
    public logDetail: boolean = true;

    /** 対象ノードに存在する Collider2D(use2DPhysics が true のとき) */
    private _collider2D: Collider2D | null = null;

    /** 対象ノードに存在する PhysicsCollider(use2DPhysics が false のとき) */
    private _collider3D: PhysicsCollider | null = null;

    /** 現在の可視化状態(システムに設定したフラグの状態) */
    private _isVisible: boolean = false;

    onLoad () {
        // 対象となる Collider コンポーネントを取得しておく
        if (this.use2DPhysics) {
            this._collider2D = this.getComponent(Collider2D);
            if (!this._collider2D) {
                error('[HitboxVisualizer] use2DPhysics=true ですが、このノードには Collider2D がアタッチされていません。ノード名:', this.node.name);
            }
        } else {
            this._collider3D = this.getComponent(PhysicsCollider);
            if (!this._collider3D) {
                error('[HitboxVisualizer] use2DPhysics=false ですが、このノードには PhysicsCollider(BoxCollider など)がアタッチされていません。ノード名:', this.node.name);
            }
        }

        // 入力イベント登録
        if (this.allowKeyToggle) {
            input.on(Input.EventType.KEY_DOWN, this._onKeyDown, this);
        }
    }

    start () {
        // 起動時の可視化状態を設定
        if (this.enableOnStart) {
            this.setVisible(true);
        } else {
            this.setVisible(false);
        }
    }

    onDestroy () {
        // 入力イベント解除
        if (this.allowKeyToggle) {
            input.off(Input.EventType.KEY_DOWN, this._onKeyDown, this);
        }
    }

    /**
     * デバッグ表示を有効化 / 無効化する公開メソッド。
     * 外部スクリプトから直接呼び出してもよい(ただし外部依存は必須ではない)。
     */
    public setVisible (visible: boolean) {
        this._isVisible = visible;

        if (this.use2DPhysics) {
            this._apply2DDebugFlags(visible);
        } else {
            this._apply3DDebugFlags(visible);
        }

        if (this.logDetail) {
            const target = this.use2DPhysics ? '2D Physics' : '3D Physics';
            // eslint-disable-next-line no-console
            console.log(`[HitboxVisualizer] ${target} hitbox debug draw is now ${visible ? 'ENABLED' : 'DISABLED'}. Node: ${this.node.name}`);
        }
    }

    /**
     * 現在の可視化状態を取得。
     */
    public isVisible (): boolean {
        return this._isVisible;
    }

    /**
     * 現在の可視化状態を反転させる(トグル)。
     */
    public toggleVisible () {
        this.setVisible(!this._isVisible);
    }

    // ------------------------
    // 内部処理
    // ------------------------

    private _onKeyDown (event: EventKeyboard) {
        if (!this.allowKeyToggle) {
            return;
        }

        if (event.keyCode === this.toggleKeyCode) {
            // Collider が存在しない場合は警告を出して何もしない
            if (this.use2DPhysics) {
                if (!this._collider2D) {
                    warn('[HitboxVisualizer] Collider2D が見つからないため、トグルできません。ノード名:', this.node.name);
                    return;
                }
            } else {
                if (!this._collider3D) {
                    warn('[HitboxVisualizer] PhysicsCollider が見つからないため、トグルできません。ノード名:', this.node.name);
                    return;
                }
            }

            this.toggleVisible();
        }
    }

    /**
     * 2D物理のデバッグ描画フラグを設定。
     */
    private _apply2DDebugFlags (visible: boolean) {
        const physics2D = PhysicsSystem2D.instance;

        if (!physics2D) {
            error('[HitboxVisualizer] PhysicsSystem2D.instance が利用できません。2D物理が有効になっているか確認してください。');
            return;
        }

        if (visible) {
            // 代表的なフラグをすべてONにする(必要に応じて調整)
            physics2D.debugDrawFlags =
                EPhysics2DDrawFlags.Aabb |
                EPhysics2DDrawFlags.Pair |
                EPhysics2DDrawFlags.CenterOfMass |
                EPhysics2DDrawFlags.Joint |
                EPhysics2DDrawFlags.Shape;
        } else {
            physics2D.debugDrawFlags = EPhysics2DDrawFlags.None;
        }
    }

    /**
     * 3D物理のデバッグ描画フラグを設定。
     */
    private _apply3DDebugFlags (visible: boolean) {
        const physics3D = PhysicsSystem.instance;

        if (!physics3D) {
            error('[HitboxVisualizer] PhysicsSystem.instance が利用できません。3D物理が有効になっているか確認してください。');
            return;
        }

        if (visible) {
            // 代表的なフラグをすべてONにする(必要に応じて調整)
            physics3D.debugDrawFlags =
                EPhysicsDrawFlags.AABB |
                EPhysicsDrawFlags.PAIR |
                EPhysicsDrawFlags.CONTACT |
                EPhysicsDrawFlags.JOINT |
                EPhysicsDrawFlags.SHAPE;
        } else {
            physics3D.debugDrawFlags = EPhysicsDrawFlags.NONE;
        }
    }
}

コードのポイント解説

  • onLoad
    • use2DPhysics の値に応じて、Collider2D または PhysicsCollidergetComponent で取得。
    • 見つからない場合は error() でエラーログを出し、防御的に実装。
    • allowKeyToggle が true の場合、input.on(KEY_DOWN) でキーボードイベントを登録。
  • start
    • enableOnStart に応じて setVisible(true/false) を呼び、起動時の可視化状態を決定。
  • onDestroy
    • 登録したキーボードイベントを input.off で解除し、リークを防止。
  • setVisible / toggleVisible / isVisible
    • デバッグ表示のON/OFFを行う公開API。
    • 内部で _apply2DDebugFlags または _apply3DDebugFlags を呼び出し、物理システムのフラグを切り替える。
    • logDetail が true のとき、現在の状態を console.log で表示。
  • _onKeyDown
    • allowKeyToggle が true のときのみ動作。
    • toggleKeyCode と一致するキーが押されたら toggleVisible() を呼び出す。
    • Collider が存在しない場合は warn() で警告を出し、何もしない。
  • _apply2DDebugFlags / _apply3DDebugFlags
    • それぞれ PhysicsSystem2D.instancePhysicsSystem.instance にアクセスし、debugDrawFlags を設定。
    • 可視化ONのときは、AABB / Shape / Joint など代表的なフラグをまとめてON にしている。
    • OFFのときは None / NONE をセットして完全に非表示。
    • 物理システムが利用できない場合は error() でエラーを通知。

使用手順と動作確認

ここからは、実際に Cocos Creator 3.8.7 のエディタ上で HitboxVisualizer を使う手順を説明します。

1. スクリプトファイルの作成

  1. Assets パネルでフォルダを選択(例: assets/scripts)。
  2. 右クリック → CreateTypeScript を選択。
  3. ファイル名を HitboxVisualizer.ts にする。
  4. 自動生成された中身をすべて削除し、前章で示した TypeScriptコード全体 を貼り付けて保存。

2. 2D物理用のテスト(Collider2D)

2Dゲームや UI の当たり判定を確認したい場合の例です。

  1. 2D物理を有効化
    • メインメニュー → ProjectProject Settings を開く。
    • ModulePhysics の設定で、Physics2D が有効になっていることを確認。
  2. テスト用ノードを作成
    • Hierarchy パネルで右クリック → Create2D ObjectSprite などを選択。
    • ノード名を例として TestBox2D に変更。
  3. Collider2D を追加
    • TestBox2D ノードを選択。
    • Inspector の Add Component ボタンをクリック。
    • Physics 2DBoxCollider2D(または他の Collider2D)を追加。
  4. HitboxVisualizer をアタッチ
    • 同じく TestBox2D ノードを選択した状態で、Add ComponentCustomHitboxVisualizer を選択。
  5. Inspector でプロパティを設定
    • use2DPhysics: ON(true)
    • enableOnStart: まずは ON(true) にして、起動直後に可視化されることを確認。
    • allowKeyToggle: ON(true)
    • toggleKeyCode: デフォルトの KEY_H のままでOK。
    • logDetail: デバッグ中は ON(true) にしておくと状態が分かりやすい。
  6. プレビューで確認
    • 上部ツールバーの Play ボタン(または Preview)を押してゲームを実行。
    • シーンビューまたはゲームビュー上で、TestBox2D の周りに 当たり判定の枠線や形状 が表示されていることを確認。
    • キーボードの H キー を押すと、デバッグ表示が ON/OFF で切り替わる。
    • コンソールに
      [HitboxVisualizer] 2D Physics hitbox debug draw is now ENABLED. Node: TestBox2D
      [HitboxVisualizer] 2D Physics hitbox debug draw is now DISABLED. Node: TestBox2D
              

      のようなログが出ていれば正常動作。

3. 3D物理用のテスト(PhysicsCollider)

3Dゲームなどで 3D Collider の形状を確認したい場合の例です。

  1. 3D物理を有効化
    • メインメニュー → ProjectProject Settings
    • Physics や Module 設定で Physics(3D)が有効になっていることを確認。
  2. テスト用ノードを作成
    • Hierarchy パネルで右クリック → Create3D ObjectCube などを選択。
    • ノード名を例として TestBox3D に変更。
  3. PhysicsCollider(例: BoxCollider)を追加
    • TestBox3D ノードを選択。
    • Inspector → Add ComponentPhysicsBoxCollider を追加。
  4. HitboxVisualizer をアタッチ
    • TestBox3D ノードを選択した状態で、Add ComponentCustomHitboxVisualizer を追加。
  5. Inspector でプロパティを設定
    • use2DPhysics: OFF(false)(3D物理を対象にするため)。
    • enableOnStart: ON(true)
    • allowKeyToggle: ON(true)
    • toggleKeyCode: 任意(デフォルト KEY_H でOK)。
    • logDetail: ON(true)
  6. プレビューで確認
    • ゲームを実行。
    • シーン内の TestBox3D 周辺に、3D Collider のワイヤーフレームが表示される。
    • H キー で表示がON/OFFされることを確認。
    • コンソールには
      [HitboxVisualizer] 3D Physics hitbox debug draw is now ENABLED. Node: TestBox3D
      [HitboxVisualizer] 3D Physics hitbox debug draw is now DISABLED. Node: TestBox3D
              

      のようなログが出力される。

4. よくあるつまずきポイント

  • Collider が無いのに use2DPhysics/use2DPhysics の設定だけ変えた場合
    • コンソールに
      [HitboxVisualizer] use2DPhysics=true ですが、このノードには Collider2D がアタッチされていません。
              

      などのエラーが出ます。

    • 対象ノードに 正しい種類の Collider コンポーネント が付いているか確認してください。
  • 物理システム自体が無効な場合
    • 2D/3D 物理モジュールがプロジェクト設定で無効だと、
      PhysicsSystem2D.instancePhysicsSystem.instance が正しく動作しないことがあります。
    • その場合はエラーが出るので、Project Settings → Physics / Module で有効化してください。
  • 複数の HitboxVisualizer をシーンに置いた場合
    • 物理デバッグ描画は システム単位 なので、最後に setVisible したコンポーネントの状態が全体に適用されます。
    • 運用としては、シーンに1つだけ配置するか、どれを「マスター」にするか決めておくと混乱しません。

まとめ

この HitboxVisualizer コンポーネントを導入すると、

  • ノードにアタッチするだけで 2D/3D の当たり判定を即座に可視化できる。
  • キー入力(デフォルト H)で いつでも ON/OFF 切り替え ができる。
  • 外部の GameManager やシングルトンに依存せず、このスクリプト単体で完結している。
  • Collider が無い・物理システムが無効などの状況でも、エラーログで原因が分かる防御的実装になっている。

当たり判定のチューニングや物理挙動のデバッグは、目視で形状を確認できるかどうかで効率が大きく変わります。
HitboxVisualizer をプロジェクトの標準ツールとして組み込んでおけば、どのシーンでも同じ操作感でヒットボックスを確認でき、デバッグ時間の短縮に大きく貢献します。

必要に応じて、

  • 2D/3D それぞれで有効にしたい debugDrawFlags の種類を調整する
  • キー入力だけでなく、UI ボタンから setVisible() を呼び出す

といった拡張も簡単に行えます。
まずはこの記事のコードをそのまま導入し、自分のプロジェクトで当たり判定の可視化を試してみてください。

Godot 4ゲーム制作 実践ドリル 100本ノック

新品価格
¥1,250から
(2025/12/13 21:27時点)

Godot4& GDScriptではじめる 2Dゲーム開発レシピ

新品価格
¥590から
(2025/12/13 21:46時点)

Unity 6 C#スクリプト 100本ノック

新品価格
¥1,230から
(2025/12/29 10:28時点)

Cocos Creator100本ノックTypeScriptで書く!

新品価格
¥1,250から
(2025/12/29 10:32時点)

URLをコピーしました!