【Cocos Creator 3.8】GodMode(無敵モード)の実装:アタッチするだけで「HPが減らず、攻撃判定を無視する」デバッグ用スクリプト
この記事では、任意のキャラクターノードにアタッチするだけで「HPが減らない」「攻撃判定を無視する」状態を実現する、デバッグ用の汎用コンポーネント GodMode を実装します。
既存のダメージ処理や HP 管理ロジックを一切変更せず、「HP を減らす側」からのアクセスをこのコンポーネントに集約することで、インスペクタで GodMode の ON/OFF を切り替えるだけで無敵モードを制御できるように設計します。
コンポーネントの設計方針
1. 外部依存を排除するための考え方
「HP が減らなくなる」「攻撃判定を無視する」という仕様は、本来であればゲーム固有の HP 管理やダメージ処理に強く依存します。しかし、本記事の条件では「他のカスタムスクリプトに依存してはならない」ため、以下のように設計します。
- HP の減少は「減らす側」から GodMode に問い合わせるという運用にする。
- 攻撃判定の無視も「攻撃を適用する側」が GodMode に問い合わせるという運用にする。
- このために、どのスクリプトからでも呼び出せる、シンプルな静的 API を提供する。
- GodMode 自体は、特定の HP コンポーネントや GameManager に依存しない。
つまり、GodMode は「無敵状態かどうかを教えてくれるコンポーネント」であり、HP 変数を直接持つ必要はありません。既存のダメージ処理側で:
// 例: 既存のダメージ処理側(あなたのゲームコード)
if (!GodMode.isNodeInvincible(targetNode)) {
targetHp -= damage;
}
のように呼び出すだけで、GodMode がアタッチされたノードだけダメージを無視できるようにします。
また、攻撃判定を無視する用途として、コリジョンイベント内で「このノードに GodMode が付いていればダメージ処理をスキップする」という書き方を想定しています。
2. インスペクタで設定可能なプロパティ
GodMode コンポーネントに持たせるプロパティは以下の通りです。
- enabledInEditorPreview: boolean
- ツールチップ: 「エディタのプレビュー再生中(Play / Simulate)でも GodMode を有効にするか」
- デフォルト:
true - 開発時のデバッグを想定。ビルドした本番環境では無効にしたい場合の切り替え用。
- enabledInReleaseBuild: boolean
- ツールチップ: 「ビルドした実機・本番環境でも GodMode を有効にするか」
- デフォルト:
false - 意図せず無敵が本番に残らないよう、基本はオフ。QA 用にオンにする場合などに使う。
- startAsInvincible: boolean
- ツールチップ: 「ゲーム開始時から無敵状態にするか」
- デフォルト:
true - 起動直後から常に無敵にしたい場合は
true。テスト用に一時的にオン/オフを切り替えたいときに使う。
- logWhenBlocked: boolean
- ツールチップ: 「GodMode によりダメージや攻撃がブロックされたとき、ログを出力するか」
- デフォルト:
false - 有効にすると、ダメージ処理側が
GodModeを参照しているか確認しやすくなる。
- debugLabelNode: Node | null
- ツールチップ: 「無敵状態を表示するための Label ノード(任意)」
- デフォルト:
null - 任意で指定すると、「GOD」などのテキストを表示して無敵状態を視覚的に確認できる。
- 指定されている場合は
Labelコンポーネントを自動取得し、なければエラーログ。
- debugLabelText: string
- ツールチップ: 「無敵時に表示するテキスト」
- デフォルト:
"GOD" debugLabelNodeが設定されている場合にのみ使用。
3. 提供する静的 API
他のスクリプトから簡単に参照できるよう、以下の静的メソッドを提供します。
GodMode.isNodeInvincible(node: Node | null | undefined): boolean- 指定したノードに有効な
GodModeコンポーネントがアタッチされていればtrue。 - アタッチされていない、もしくは現在無敵が無効なら
false。
- 指定したノードに有効な
GodMode.tryBlockDamage(node: Node | null | undefined, reason?: string): boolean- 指定ノードが無敵なら
true(= ダメージをブロックすべき)、そうでなければfalse。 logWhenBlockedが ON の場合、ブロック時にログを出す。- ダメージ処理側で
if (GodMode.tryBlockDamage(target, "enemyHit")) return;のように使う想定。
- 指定ノードが無敵なら
GodMode.setInvincible(node: Node | null | undefined, value: boolean): void- 指定ノードにアタッチされた
GodModeがあれば、その無敵状態をコードから切り替える。 - 存在しない場合は何もせず、警告ログを出す。
- 指定ノードにアタッチされた
このように、「GodMode をアタッチしたノード」だけが自然に無敵対象になる設計にすることで、外部の GameManager や HP コンポーネントに依存しない、再利用しやすいコンポーネントになります。
TypeScriptコードの実装
import { _decorator, Component, Node, Label, game, sys, isValid } from 'cc';
const { ccclass, property } = _decorator;
/**
* GodMode
* 任意のノードにアタッチするだけで「無敵フラグ」を提供するコンポーネント。
* 実際のダメージ処理側は GodMode.isNodeInvincible / tryBlockDamage を参照して、
* ダメージや攻撃適用をスキップしてください。
*/
@ccclass('GodMode')
export class GodMode extends Component {
@property({
tooltip: 'エディタのプレビュー再生中(Play / Simulate)でも GodMode を有効にするか',
})
public enabledInEditorPreview: boolean = true;
@property({
tooltip: 'ビルドした実機・本番環境でも GodMode を有効にするか',
})
public enabledInReleaseBuild: boolean = false;
@property({
tooltip: 'ゲーム開始時から無敵状態にするか',
})
public startAsInvincible: boolean = true;
@property({
tooltip: 'GodMode によりダメージや攻撃がブロックされたとき、ログを出力するか',
})
public logWhenBlocked: boolean = false;
@property({
tooltip: '無敵状態を表示するための Label ノード(任意)',
})
public debugLabelNode: Node | null = null;
@property({
tooltip: '無敵時に表示するテキスト(debugLabelNode が指定されている場合のみ使用)',
})
public debugLabelText: string = 'GOD';
/**
* 現在このコンポーネントが管理する無敵状態フラグ
* (実際に有効かどうかは、エディタ/ビルド設定も加味して判定される)
*/
private _isInvincible: boolean = false;
/** 無敵表示用 Label(任意) */
private _debugLabel: Label | null = null;
/**
* このノードにアタッチされた GodMode インスタンスを取得するヘルパー。
* null/undefined や無効ノードにも安全に対応。
*/
private static _getInstance(node: Node | null | undefined): GodMode | null {
if (!node || !isValid(node, true)) {
return null;
}
const comp = node.getComponent(GodMode);
if (!comp || !isValid(comp, true)) {
return null;
}
return comp;
}
/**
* 指定ノードが無敵状態かどうかを返す静的メソッド。
* 他のスクリプトからの参照用。
*/
public static isNodeInvincible(node: Node | null | undefined): boolean {
const inst = GodMode._getInstance(node);
if (!inst) {
return false;
}
return inst.isInvincible();
}
/**
* 指定ノードに対するダメージや攻撃を GodMode によってブロックすべきかどうかを返す。
* true が返ってきた場合は、ダメージ処理を行わず return するなどの対応をしてください。
* @param node 対象ノード
* @param reason 任意の識別文字列(ログ出力時に利用)
*/
public static tryBlockDamage(node: Node | null | undefined, reason?: string): boolean {
const inst = GodMode._getInstance(node);
if (!inst) {
return false;
}
if (!inst.isInvincible()) {
return false;
}
if (inst.logWhenBlocked) {
const nodeName = node?.name ?? '(unknown)';
const extra = reason ? ` reason=${reason}` : '';
console.log(`[GodMode] ダメージ/攻撃をブロック: node=${nodeName}${extra}`);
}
return true;
}
/**
* コードから無敵状態を切り替えたい場合に使用する静的メソッド。
* 対象ノードに GodMode が付いていない場合は警告ログを出すだけで何もしません。
*/
public static setInvincible(node: Node | null | undefined, value: boolean): void {
const inst = GodMode._getInstance(node);
if (!inst) {
const nodeName = node?.name ?? '(null)';
console.warn(`[GodMode] setInvincible が呼ばれましたが、対象ノードに GodMode がアタッチされていません: node=${nodeName}`);
return;
}
inst.setInvincible(value);
}
/**
* このインスタンスが現在「実際に」無敵かどうか。
* エディタ/ビルドの設定も考慮して判定します。
*/
public isInvincible(): boolean {
if (!this._isInvincible) {
return false;
}
const isEditor = !sys.isNative && (sys.platform === sys.Platform.MACOS || sys.platform === sys.Platform.WINDOWS) && game.isPersistRootNode !== undefined;
// 上記 isEditor 判定はあくまで簡易。実際の editor 判定は engine 内部に依存するため、
// ここでは「ビルド結果かどうか」を sys.isNative / sys.isBrowser などから推定する。
// よりシンプルに、ビルドかどうかだけを見る実装にしておく。
const isReleaseBuild = !CC_EDITOR; // CC_EDITOR はエディタ上でのみ true になるグローバル定数
// エディタ上のプレビュー再生
if (!isReleaseBuild) {
return this.enabledInEditorPreview;
}
// ビルドされた実行環境
return this.enabledInReleaseBuild;
}
/**
* 内部フラグを直接切り替えるインスタンスメソッド。
* 外部からはできるだけ static setInvincible を使うと、存在チェックもしてくれるので安全。
*/
public setInvincible(value: boolean): void {
this._isInvincible = value;
this._updateDebugLabel();
}
onLoad() {
// デバッグラベルの取得
if (this.debugLabelNode) {
this._debugLabel = this.debugLabelNode.getComponent(Label);
if (!this._debugLabel) {
console.error('[GodMode] debugLabelNode に Label コンポーネントが見つかりません。Label を追加するか、debugLabelNode を未設定にしてください。');
}
}
}
start() {
// 開始時の無敵状態を設定
this._isInvincible = this.startAsInvincible;
this._updateDebugLabel();
}
/**
* デバッグ用ラベルの表示更新。
* 無敵が有効ならテキストを表示、無効なら空文字にします。
*/
private _updateDebugLabel(): void {
if (!this._debugLabel) {
return;
}
if (this.isInvincible()) {
this._debugLabel.string = this.debugLabelText;
} else {
this._debugLabel.string = '';
}
}
/**
* エディタ上でプロパティが変更されたときにもラベルを更新できるようにする。
*/
update(deltaTime: number) {
// 毎フレーム重い処理はしない。
// ここではラベルが設定されていれば、現在の状態に応じて表示を維持するだけ。
if (this._debugLabel) {
// isInvincible() 内でエディタ/ビルドの条件も考慮される。
const shouldShow = this.isInvincible();
const expectedText = shouldShow ? this.debugLabelText : '';
if (this._debugLabel.string !== expectedText) {
this._debugLabel.string = expectedText;
}
}
}
}
コードの要点解説
- onLoad
debugLabelNodeが指定されていればLabelコンポーネントを取得。- 見つからない場合は
console.errorで明確に通知し、防御的に実装。
- start
startAsInvincibleに応じて_isInvincibleを初期化。- ラベル表示も初期状態に更新。
- update
- 毎フレーム、ラベルが存在する場合のみ、現在の無敵状態に応じたテキストを維持。
- テキストが変わるときだけ更新することで、無駄な代入を避ける。
- 静的メソッド群
isNodeInvincible:指定ノードの無敵状態を簡単に確認できる。tryBlockDamage:ダメージ処理側が「無敵なら即 return」するためのヘルパー。setInvincible:コードから無敵の ON/OFF を切り替えるための入口。- いずれも
_getInstanceでノードとコンポーネントの有効性をチェックし、防御的に実装。
使用手順と動作確認
1. スクリプトファイルの作成
- Assets パネルで右クリック → Create → TypeScript を選択します。
- ファイル名を
GodMode.tsにします。 - 自動生成された中身をすべて削除し、本記事の
GodModeコードを貼り付けて保存します。
2. テスト用ノードの作成
- Hierarchy パネルで右クリック → Create → 2D Object → Sprite などを選択し、テスト用のキャラクターノードを作成します。
- ノード名を
Playerなど分かりやすい名前に変更しておきます。
3. GodMode コンポーネントをアタッチ
- Hierarchy で
Playerノードを選択します。 - Inspector の下部にある Add Component ボタンをクリックします。
- Custom → GodMode を選択し、コンポーネントを追加します。
4. デバッグ用ラベルの設定(任意)
無敵状態を画面上で視覚的に確認したい場合は、Label ノードを追加して紐づけます。
- Hierarchy で
Playerノードを右クリック → Create → 2D Object → Label を選択します。 - 生成された Label ノードの名前を
GodLabelなどに変更します。 GodLabelを選択し、Inspector で Label コンポーネントが付いていることを確認します(なければ Add Component → UI → Label から追加)。- 再度
Playerノードを選択し、Inspector でGodModeコンポーネントを確認します。 - Debug Label Node プロパティに、Hierarchy から
GodLabelノードをドラッグ&ドロップします。 - Debug Label Text を
GODやINVINCIBLEなど好みの表示文字列に変更します。
5. インスペクタでのプロパティ設定例
テスト用の設定例:
- Enabled In Editor Preview:
true - Enabled In Release Build:
false - Start As Invincible:
true - Log When Blocked:
true - Debug Label Node:
GodLabel(任意) - Debug Label Text:
GOD
この状態でエディタ上で再生すると、Player ノードが無敵として扱われ、GodLabel に「GOD」と表示されます。
6. ダメージ処理側での利用例
最後に、あなたの既存のダメージ処理コードに、GodMode を参照する1行を追加するだけで無敵モードを適用できます。
例1: 衝突イベント内でのダメージ処理
// 例: 敵の攻撃スクリプト内(あなたのゲームコード)
import { _decorator, Component, Collider2D, IPhysics2DContact } from 'cc';
import { GodMode } from './GodMode';
const { ccclass, property } = _decorator;
@ccclass('EnemyAttack')
export class EnemyAttack extends Component {
@property
public damage: number = 10;
onLoad() {
const col = this.getComponent(Collider2D);
if (col) {
col.on('onBeginContact', this.onBeginContact, this);
} else {
console.error('[EnemyAttack] Collider2D が見つかりません。攻撃判定用の Collider2D を追加してください。');
}
}
private onBeginContact(self: Collider2D, other: Collider2D, contact: IPhysics2DContact | null) {
const targetNode = other.node;
// ★ GodMode による無敵チェックを追加
if (GodMode.tryBlockDamage(targetNode, 'enemyAttack')) {
// 無敵ならダメージ処理を行わず return
return;
}
// ここに通常のダメージ処理を書く
// 例: targetHp -= this.damage; など
}
}
例2: 直接 HP を減らす関数内でのチェック
import { GodMode } from './GodMode';
// 例: Player の HP 管理スクリプト内
applyDamage(damage: number) {
// this.node に GodMode が付いている場合だけブロック
if (GodMode.tryBlockDamage(this.node, 'playerDamage')) {
return;
}
this.hp -= damage;
}
このように、ダメージ処理の入り口に GodMode チェックを1行追加するだけで、アタッチされたノードが無敵化します。
7. プレビューでの動作確認
- エディタ右上の ▶(再生) ボタンを押してゲームをプレビューします。
- 敵やトラップなど、ダメージを与えるオブジェクトに近づいて当たってみます。
GodModeがアタッチされているノードに対しては、HP が減らない・ダメージ処理が呼ばれないことを確認してください。- Log When Blocked を
trueにしている場合、Console に[GodMode] ダメージ/攻撃をブロック: node=Player reason=enemyAttackのようなログが出ていることも確認できます。
まとめ
GodModeコンポーネントは、任意のノードにアタッチするだけで「無敵フラグ」を提供する汎用スクリプトです。- 外部の GameManager や HP スクリプトに依存せず、静的メソッド
isNodeInvincible/tryBlockDamage/setInvincibleを通じて、既存コードに最小限の変更で統合できます。 - インスペクタのプロパティから
- エディタプレビューでのみ有効にするか
- ビルド環境でも有効にするか
- 開始時から無敵にするか
- ブロック時にログを出すか
- 無敵表示用ラベルのテキスト
を柔軟に切り替えられるため、デバッグ用途だけでなく QA やチート実装にも流用可能です。
- このコンポーネント単体で完結しているため、他のプロジェクトにもそのままコピーして再利用できます。
ゲーム開発中の「被ダメージテスト」「ステージの後半まで一気に進みたい」といったシーンで、GodMode をアタッチしておくだけで効率よくデバッグできるようになります。既存のダメージ処理に1行のチェックを加えるだけなので、ぜひ自分のプロジェクトに組み込んでみてください。




