【Cocos Creator】アタッチするだけ!SpringBoard (ジャンプ台)の実装方法【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】SpringBoard(ジャンプ台)の実装:アタッチするだけで「踏んだ瞬間にプレイヤーを跳ね飛ばす」汎用スクリプト

このガイドでは、ノードにアタッチするだけで「その上に乗ったキャラクターの縦方向速度(Velocity.y)を強制的に上書きして跳ね飛ばす」汎用コンポーネント SpringBoard を実装します。

プレイヤー側には「Rigidbody2D を持っていること」だけを前提とし、GameManager などの外部スクリプトに一切依存しない完全独立コンポーネントとして設計します。
ジャンプ台の跳ねる強さ・当たり判定モード・対象レイヤーなどは、すべてインスペクタから調整できるようにします。


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

1. 機能要件の整理

  • このコンポーネントをアタッチしたノードは「ジャンプ台」として振る舞う。
  • ジャンプ台と接触した Rigidbody2D を持つノードlinearVelocity.y を、指定した値に強制上書きする。
  • 横方向の速度(linearVelocity.x)は維持し、縦方向だけを変更する。
  • 接触判定は 2D 物理(Collider2D)を利用し、onBeginContact / onTriggerEnter のどちらでも動作できるようにする。
  • プレイヤー以外(敵・弾など)には反応させないために、対象レイヤー(グループ)をインスペクタで指定可能にする。
  • 「上から乗ったときだけ反応する」モードと、「どの方向から当たっても反応する」モードを切り替え可能にする。
  • SpringBoard 自身に必要な標準コンポーネント(Collider2D)が存在しない場合は、エラーログを出して利用者に通知する。

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

以下のプロパティを @property で公開し、インスペクタから調整できるようにします。

  • bounceVelocityY: number
    ・ツールチップ: 踏んだ対象の Rigidbody2D.linearVelocity.y をこの値に上書きします。
    ・役割: 跳ねる強さ。
    ・正の値で上方向に跳ね上げる想定(例: 800)。
    ・ゲームのスケールに合わせて調整可能。
  • useTrigger: boolean
    ・ツールチップ: Collider2D を Trigger として扱う場合は ON にします。
    ・役割: コライダーを トリガーとして扱うか、通常の物理接触として扱うかの切り替え。
    ・ON の場合: onTriggerEnter で判定。
    ・OFF の場合: onBeginContact で判定。
  • targetGroupName: string
    ・ツールチップ: 跳ね飛ばしたい対象の Group 名(例: "player")。空欄なら全てに反応します。
    ・役割: 反応させたい対象のグループ名。
    ・空文字の場合は全てのグループに反応
    ・”player” など、プロジェクトで設定している Group 名を入力。
  • onlyFromAbove: boolean
    ・ツールチップ: 対象が上から落ちてきた場合だけ有効にします。
    ・役割: 上から踏まれたときだけ反応させるかどうか。
    ・ON の場合: 対象の Rigidbody2D の linearVelocity.y <= 0 のときのみ有効。
    ・OFF の場合: どの方向から当たっても有効。
  • debugLog: boolean
    ・ツールチップ: ON にすると、コンソールにデバッグログを出力します。
    ・役割: 開発中のデバッグ用。ON にすると、接触判定やエラー情報をログ出力。

これらのプロパティにより、SpringBoard.ts 単体で、さまざまなジャンプ台挙動を柔軟に設定できるようになります。


TypeScriptコードの実装

以下が、完成した SpringBoard コンポーネントの TypeScript コードです。


import { _decorator, Component, Node, RigidBody2D, Collider2D, IPhysics2DContact, Contact2DType, Vec2, director, PhysicsSystem2D, ERigidBody2DType } from 'cc';
const { ccclass, property } = _decorator;

/**
 * SpringBoard(ジャンプ台)
 * - このコンポーネントを持つノードに 2D Collider が必要です。
 * - 接触した Rigidbody2D を持つノードの linearVelocity.y を bounceVelocityY に強制上書きします。
 */
@ccclass('SpringBoard')
export class SpringBoard extends Component {

    @property({
        tooltip: '踏んだ対象の Rigidbody2D.linearVelocity.y をこの値に上書きします。(例: 800)'
    })
    public bounceVelocityY: number = 800;

    @property({
        tooltip: 'Collider2D を Trigger として扱う場合は ON にします。ON: onTriggerEnter / OFF: onBeginContact を使用します。'
    })
    public useTrigger: boolean = false;

    @property({
        tooltip: '跳ね飛ばしたい対象の Group 名(例: "player")。空欄なら全ての Group に反応します。'
    })
    public targetGroupName: string = 'player';

    @property({
        tooltip: '対象が上から落ちてきた場合だけ有効にします(対象の Velocity.y が 0 以下のときのみ反応)。'
    })
    public onlyFromAbove: boolean = true;

    @property({
        tooltip: 'ON にすると、接触時の情報をコンソールにログ出力します。'
    })
    public debugLog: boolean = false;

    private _collider: Collider2D | null = null;

    onLoad() {
        // 2D 物理が有効かどうか確認(ビルド設定で無効にしていると動かない)
        if (!PhysicsSystem2D.instance) {
            console.error('[SpringBoard] PhysicsSystem2D が有効になっていません。Project Settings で 2D Physics を有効にしてください。');
        }

        // このノードに Collider2D が付いているか確認
        this._collider = this.getComponent(Collider2D);
        if (!this._collider) {
            console.error('[SpringBoard] このノードには Collider2D コンポーネントが必要です。BoxCollider2D などを追加してください。');
            return;
        }

        // Trigger 設定の同期
        this._collider.sensor = this.useTrigger;

        // コンタクトイベントの登録
        this._collider.on(Contact2DType.BEGIN_CONTACT, this._onBeginContact, this);
        this._collider.on(Contact2DType.TRIGGER_ENTER, this._onTriggerEnter, this);
    }

    onDestroy() {
        if (this._collider) {
            this._collider.off(Contact2DType.BEGIN_CONTACT, this._onBeginContact, this);
            this._collider.off(Contact2DType.TRIGGER_ENTER, this._onTriggerEnter, this);
        }
    }

    /**
     * 通常の物理接触開始(useTrigger = false のときに使用)
     */
    private _onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
        if (this.useTrigger) {
            // Trigger モード時はここでは何もしない
            return;
        }
        this._tryBounce(otherCollider);
    }

    /**
     * Trigger 接触開始(useTrigger = true のときに使用)
     */
    private _onTriggerEnter(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
        if (!this.useTrigger) {
            // 通常接触モード時はここでは何もしない
            return;
        }
        this._tryBounce(otherCollider);
    }

    /**
     * 実際に対象を跳ね飛ばす処理
     */
    private _tryBounce(otherCollider: Collider2D) {
        const otherNode = otherCollider.node;

        // Group チェック(targetGroupName が空ならスキップ)
        if (this.targetGroupName && otherNode.group !== this.targetGroupName) {
            if (this.debugLog) {
                console.log(`[SpringBoard] Group が一致しないため無視: target="${this.targetGroupName}", actual="${otherNode.group}"`);
            }
            return;
        }

        // Rigidbody2D を取得
        const rb = otherNode.getComponent(RigidBody2D);
        if (!rb) {
            if (this.debugLog) {
                console.warn('[SpringBoard] 接触したノードに Rigidbody2D がありません。何も行いません。ノード名:', otherNode.name);
            }
            return;
        }

        // Kinematic / Static など、動かない Rigidbody2D には適用しない
        if (rb.type !== ERigidBody2DType.Dynamic) {
            if (this.debugLog) {
                console.log('[SpringBoard] Dynamic でない Rigidbody2D には適用しません。ノード名:', otherNode.name);
            }
            return;
        }

        // 現在の速度を取得
        const currentVel = rb.linearVelocity;

        // onlyFromAbove が ON の場合は、落下中(または上方向速度ゼロ)のときのみ反応
        if (this.onlyFromAbove && currentVel.y > 0) {
            if (this.debugLog) {
                console.log('[SpringBoard] onlyFromAbove が有効のため、上向きに移動中の対象には反応しません。ノード名:', otherNode.name);
            }
            return;
        }

        // 新しい速度を設定(x は維持し、y だけ上書き)
        const newVel = new Vec2(currentVel.x, this.bounceVelocityY);
        rb.linearVelocity = newVel;

        if (this.debugLog) {
            console.log(`[SpringBoard] 跳ね飛ばし: node=${otherNode.name}, from=(${currentVel.x.toFixed(2)}, ${currentVel.y.toFixed(2)}) to=(${newVel.x.toFixed(2)}, ${newVel.y.toFixed(2)})`);
        }
    }
}

コードのポイント解説

  • onLoad()
    PhysicsSystem2D が有効かをチェックし、無効ならエラーログを出します。
    Collider2DgetComponent で取得し、存在しない場合はエラーを出して終了します。
    useTrigger の値を this._collider.sensor に反映し、Trigger として扱うかどうかを決定します。
    Contact2DType.BEGIN_CONTACTContact2DType.TRIGGER_ENTER のイベントに、それぞれハンドラを登録します。
  • _onBeginContact / _onTriggerEnter()
    useTrigger の状態に応じて、_tryBounce() を呼ぶかどうかを切り替えています。
    ・これにより、1つのコンポーネントで Trigger / 通常接触の両方に対応できます。
  • _tryBounce()
    ・対象ノードの grouptargetGroupName と一致するかをチェック。空文字なら全て通します。
    Rigidbody2D が存在しない場合は何もせず、debugLog が ON なら警告を出します。
    ERigidBody2DType.Dynamic 以外(Static / Kinematic)は跳ね飛ばさないようにしています。
    onlyFromAbove が ON の場合は、linearVelocity.y > 0(上昇中)は無視し、落ちてきたときだけ反応させます。
    ・最終的に linearVelocity の y 成分だけを bounceVelocityY に上書きします。
  • 防御的な実装
    ・必須コンポーネント(Collider2D)が無い場合は console.error で明確に通知。
    ・対象に Rigidbody2D が無い場合や、Group が異なる場合なども、debugLog オプションで詳細を確認できます。

使用手順と動作確認

1. スクリプトの作成

  1. エディタ左下の Assets パネルで、スクリプトを置きたいフォルダ(例: assets/scripts)を選択します。
  2. フォルダ上で右クリック → CreateTypeScript を選択します。
  3. ファイル名を SpringBoard.ts に変更します。
  4. 作成された SpringBoard.ts をダブルクリックして開き、内容をすべて削除して、前章のコードをそのまま貼り付けて保存します。

2. ジャンプ台ノードの作成

  1. Hierarchy パネルで右クリック → Create2D ObjectSprite などを選択し、ジャンプ台用ノードを作成します。
  2. ノード名を分かりやすく SpringBoard などに変更します。
  3. Inspector で、このノードに Sprite コンポーネントが付いていることを確認し、任意のテクスチャ(板・バネなど)を設定します。
  4. 同じく Inspector で Add ComponentPhysics 2DBoxCollider2D を追加します。
    • サイズを Sprite の大きさに合わせます。
    • ジャンプ台を「乗れる床」にしたい場合、BoxCollider2DOffset.y を少し上にずらしても良いです。

注意: SpringBoardCollider2D が必須です。付け忘れるとコンソールにエラーが出て動作しません。

3. SpringBoard コンポーネントのアタッチ

  1. Hierarchy で先ほど作成したジャンプ台ノードを選択します。
  2. Inspector の一番下で Add ComponentCustomSpringBoard を選択します。
  3. 追加された SpringBoard コンポーネントのプロパティを設定します:
    • bounceVelocityY: 例として 800 を入力(ゲームのスケールにより 300〜1500 程度で調整)。
    • useTrigger: OFF(チェックを外す)にすると、通常の物理接触で反応します。
      コライダーを「すり抜け」にしたい場合は ON にします(この場合、BoxCollider2DSensor チェックも ON になります)。
    • targetGroupName: プレイヤーの Group 名を入力(例: player)。
      もし Group を使っていない場合や、とりあえず全て跳ね飛ばしたい場合は空欄でも構いません。
    • onlyFromAbove: 上から踏んだときだけ反応させたい場合は ON(推奨)。
      どの方向から当たっても跳ねさせたい場合は OFF にします。
    • debugLog: 動作確認中は ON にしてログを見ながら調整すると便利です。リリース前には OFF にしても良いでしょう。

4. プレイヤーノードの準備

SpringBoard は「接触した側のノードに Rigidbody2D がある」ことを前提にしています。プレイヤーを例に説明します。

  1. Hierarchy でプレイヤーノード(例: Player)を作成または選択します。
  2. Inspector で Add ComponentPhysics 2DRigidBody2D を追加します。
    • TypeDynamic に設定してください(Static / Kinematic だと跳ねません)。
    • 重力や質量はゲームに合わせて設定します。
  3. 同じく Inspector で Add ComponentPhysics 2DBoxCollider2D などを追加し、プレイヤーにコライダーを付けます。
  4. プレイヤーノードの Group を、SpringBoard の targetGroupName に指定したもの(例: player)に設定します。
    • Group の設定は、メニューの ProjectProject SettingsLayersGroup で確認・追加できます。

5. 物理設定の確認

  1. メニューから ProjectProject Settings を開きます。
  2. 左側で Physics 2D を選択し、Enable Physics(もしくは同等の有効化設定)が ON になっていることを確認します。
  3. 必要に応じて Gravity(例: (0, -980))などを調整します。

6. 動作確認

  1. Scene ビューで、プレイヤーがジャンプ台の上に落ちてくるように配置します。
  2. エディタ右上の Play(▶) ボタンを押してゲームをプレビューします。
  3. プレイヤーがジャンプ台に接触した瞬間、縦方向の速度が bounceVelocityY に上書きされ、勢いよく跳ね上がることを確認します。
  4. debugLog を ON にしている場合、コンソールに以下のようなログが出力されます:
    [SpringBoard] 跳ね飛ばし: node=Player, from=(0.00, -250.00) to=(0.00, 800.00)
  5. 跳ね具合が弱い/強すぎる場合は、bounceVelocityY を 400, 600, 1000 などに変えて再度テストし、ちょうど良い値を探します。

まとめ

この SpringBoard コンポーネントは、

  • ジャンプ台ノードにアタッチして、Collider2D を 1つ追加するだけで動作する。
  • プレイヤー側は Rigidbody2D を付けるだけで、特別なスクリプト実装は不要。
  • 跳ねる強さ(bounceVelocityY)、判定モード(Trigger / 通常接触)、対象 Group、上からのみ判定などを すべてインスペクタから調整可能
  • 他の GameManager やシングルトンに一切依存しない、完全に独立した汎用コンポーネント

応用例としては、

  • バネ床・トランポリン・ジャンプパッドなど、強さの違う複数のジャンプ台をシーンに配置する。
  • 敵やギミック専用のジャンプ台を作り、targetGroupName を分けることで、プレイヤーには反応しない仕掛けにする。
  • 一時的なハイジャンプエリアや、ギミックとしての縦移動演出に利用する。

SpringBoard.ts 1ファイルをプロジェクトに追加しておけば、どのステージでも「ジャンプ台」を即座に再利用できるようになります。
このような「アタッチするだけで完結する」コンポーネントを積み重ねていくと、Cocos Creator でのゲーム開発効率が大きく向上します。

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をコピーしました!