【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が有効かをチェックし、無効ならエラーログを出します。
・Collider2DをgetComponentで取得し、存在しない場合はエラーを出して終了します。
・useTriggerの値をthis._collider.sensorに反映し、Trigger として扱うかどうかを決定します。
・Contact2DType.BEGIN_CONTACTとContact2DType.TRIGGER_ENTERのイベントに、それぞれハンドラを登録します。 -
_onBeginContact / _onTriggerEnter()
・useTriggerの状態に応じて、_tryBounce()を呼ぶかどうかを切り替えています。
・これにより、1つのコンポーネントで Trigger / 通常接触の両方に対応できます。 -
_tryBounce()
・対象ノードのgroupがtargetGroupNameと一致するかをチェック。空文字なら全て通します。
・Rigidbody2Dが存在しない場合は何もせず、debugLogが ON なら警告を出します。
・ERigidBody2DType.Dynamic以外(Static / Kinematic)は跳ね飛ばさないようにしています。
・onlyFromAboveが ON の場合は、linearVelocity.y > 0(上昇中)は無視し、落ちてきたときだけ反応させます。
・最終的にlinearVelocityの y 成分だけをbounceVelocityYに上書きします。 -
防御的な実装
・必須コンポーネント(Collider2D)が無い場合はconsole.errorで明確に通知。
・対象にRigidbody2Dが無い場合や、Group が異なる場合なども、debugLogオプションで詳細を確認できます。
使用手順と動作確認
1. スクリプトの作成
- エディタ左下の Assets パネルで、スクリプトを置きたいフォルダ(例:
assets/scripts)を選択します。 - フォルダ上で右クリック → Create → TypeScript を選択します。
- ファイル名を
SpringBoard.tsに変更します。 - 作成された
SpringBoard.tsをダブルクリックして開き、内容をすべて削除して、前章のコードをそのまま貼り付けて保存します。
2. ジャンプ台ノードの作成
- Hierarchy パネルで右クリック → Create → 2D Object → Sprite などを選択し、ジャンプ台用ノードを作成します。
- ノード名を分かりやすく
SpringBoardなどに変更します。 - Inspector で、このノードに Sprite コンポーネントが付いていることを確認し、任意のテクスチャ(板・バネなど)を設定します。
- 同じく Inspector で Add Component → Physics 2D → BoxCollider2D を追加します。
- サイズを Sprite の大きさに合わせます。
- ジャンプ台を「乗れる床」にしたい場合、
BoxCollider2Dの Offset.y を少し上にずらしても良いです。
注意: SpringBoard は Collider2D が必須です。付け忘れるとコンソールにエラーが出て動作しません。
3. SpringBoard コンポーネントのアタッチ
- Hierarchy で先ほど作成したジャンプ台ノードを選択します。
- Inspector の一番下で Add Component → Custom → SpringBoard を選択します。
- 追加された
SpringBoardコンポーネントのプロパティを設定します:- bounceVelocityY: 例として 800 を入力(ゲームのスケールにより 300〜1500 程度で調整)。
- useTrigger: OFF(チェックを外す)にすると、通常の物理接触で反応します。
コライダーを「すり抜け」にしたい場合は ON にします(この場合、BoxCollider2Dの Sensor チェックも ON になります)。 - targetGroupName: プレイヤーの Group 名を入力(例:
player)。
もし Group を使っていない場合や、とりあえず全て跳ね飛ばしたい場合は空欄でも構いません。 - onlyFromAbove: 上から踏んだときだけ反応させたい場合は ON(推奨)。
どの方向から当たっても跳ねさせたい場合は OFF にします。 - debugLog: 動作確認中は ON にしてログを見ながら調整すると便利です。リリース前には OFF にしても良いでしょう。
4. プレイヤーノードの準備
SpringBoard は「接触した側のノードに Rigidbody2D がある」ことを前提にしています。プレイヤーを例に説明します。
- Hierarchy でプレイヤーノード(例:
Player)を作成または選択します。 - Inspector で Add Component → Physics 2D → RigidBody2D を追加します。
- Type は Dynamic に設定してください(Static / Kinematic だと跳ねません)。
- 重力や質量はゲームに合わせて設定します。
- 同じく Inspector で Add Component → Physics 2D → BoxCollider2D などを追加し、プレイヤーにコライダーを付けます。
- プレイヤーノードの Group を、SpringBoard の
targetGroupNameに指定したもの(例:player)に設定します。- Group の設定は、メニューの Project → Project Settings → Layers → Group で確認・追加できます。
5. 物理設定の確認
- メニューから Project → Project Settings を開きます。
- 左側で Physics 2D を選択し、Enable Physics(もしくは同等の有効化設定)が ON になっていることを確認します。
- 必要に応じて Gravity(例:
(0, -980))などを調整します。
6. 動作確認
- Scene ビューで、プレイヤーがジャンプ台の上に落ちてくるように配置します。
- エディタ右上の Play(▶) ボタンを押してゲームをプレビューします。
- プレイヤーがジャンプ台に接触した瞬間、縦方向の速度が
bounceVelocityYに上書きされ、勢いよく跳ね上がることを確認します。 debugLogを ON にしている場合、コンソールに以下のようなログが出力されます:[SpringBoard] 跳ね飛ばし: node=Player, from=(0.00, -250.00) to=(0.00, 800.00)- 跳ね具合が弱い/強すぎる場合は、
bounceVelocityYを 400, 600, 1000 などに変えて再度テストし、ちょうど良い値を探します。
まとめ
この SpringBoard コンポーネントは、
- ジャンプ台ノードにアタッチして、Collider2D を 1つ追加するだけで動作する。
- プレイヤー側は Rigidbody2D を付けるだけで、特別なスクリプト実装は不要。
- 跳ねる強さ(
bounceVelocityY)、判定モード(Trigger / 通常接触)、対象 Group、上からのみ判定などを すべてインスペクタから調整可能。 - 他の GameManager やシングルトンに一切依存しない、完全に独立した汎用コンポーネント。
応用例としては、
- バネ床・トランポリン・ジャンプパッドなど、強さの違う複数のジャンプ台をシーンに配置する。
- 敵やギミック専用のジャンプ台を作り、
targetGroupNameを分けることで、プレイヤーには反応しない仕掛けにする。 - 一時的なハイジャンプエリアや、ギミックとしての縦移動演出に利用する。
SpringBoard.ts 1ファイルをプロジェクトに追加しておけば、どのステージでも「ジャンプ台」を即座に再利用できるようになります。
このような「アタッチするだけで完結する」コンポーネントを積み重ねていくと、Cocos Creator でのゲーム開発効率が大きく向上します。




