こんにちは、ハートランド・データ株式会社の増田です。
社内の"技術者研修"という活動で、ゲーム開発プロジェクトに参加したので、そちらの活動ブログになります。
ゲーム開発プロジェクトにて、弊社オリジナルキャラクターの"バグレスくん"をプレイヤーとして遊ぶゲームを開発することに。
2Dゲームをやってきた世代として、やっぱり"モブ"に邪魔されたい!
ということで、バグレスくんが苦手としている”お掃除”をイメージしたモブキャラを用意することにしました。
今回は、そんなお邪魔モブの実装にあたり、ハマった部分について、記事にしました。
開発環境:Godot4.5、Windows
開発言語:Godot スクリプト
成果物:Godot Windowsアプリ
制作チーム:Bloom Bit Lab. (B.B.Lab.)
想定読者:Godot開発をこれからやろうとしている、ちょっと知識のある人
※本記事のキャラクター画像は、GeminiおよびMicrosoft 365 Copilotを用いて生成しています
1.モブをうごかす
モブを追加する
詳しい手順は割愛します!
こちらのサイトを参考にしました。
モブ画像を用意して、キャラクターシーンを追加するのと同様に、モブシーンを追加します。
スクリプトを実装する
スクリプトでモブを自動操縦する。
モブ(ぞうきん)が、壁や他のキャラクターといった障害物にあたるまで、左右に動く処理を作成。
# ぞうきんを左右に動かすためのスクリプト
extends CharacterBody2D
# モブの移動速度
const SPEED = 50.0
# 移動方向(1: 右, -1: 左)
var direction: int = 1
func _physics_process(delta: float) -> void:
# 重力を追加
if not is_on_floor():
velocity += get_gravity() * delta
# 左右に移動
velocity.x = direction * SPEED
move_and_slide()
# 壁や障害物に当たったら方向を反転
if is_on_wall():
direction *= -1
ポイント:
-
velocity
-
velocity.xは速度を表す(「1秒間に何ピクセル移動するか」) -
velocity.x = 50.0→ 右方向に毎秒50ピクセル移動 -
velocity.x = -50.0→ 左方向に毎秒50ピクセル移動 -
direction * SPEEDで、移動の方向と速さを決めている-
direction = 1のとき:velocity.x = 50.0(右へ) -
direction = -1のとき:velocity.x = -50.0(左へ)
-
-
move_and_slide()がこの velocity を使って実際にキャラクターを移動させる。毎フレーム呼び出されるので、継続的に移動し続ける
-
実装結果

※キャラクター画像は、GeminiおよびMicrosoft 365 Copilotを用いて生成しています
壁や別のキャラクターにぶつかると、移動する向きが反転する。問題なく実装できていそう。
2.モブに当たり判定をつける
バグレスくんがものすごい勢いで吹っ飛ぶ不具合発生
ゲーム開発もGodot開発も初心者で、GitHub Copilotにお願いして実装してたら、作ったモブにバグレスくんがぶつかると、ものすごい勢いでバグレスくんが画面外に吹き飛ぶ不具合が発生した。
解決方法
Copilotくんに聞きまくっても、原因と対策がずれていて、解決しない。自分のGodot物理エンジンの知識と理解が浅すぎて、Copilotの不具合調査に協力できていないのもよくないと思い、ちゃんと調べることにした。
参考サイトで、設定や処理を確認する。
実装した処理では、”Node2D”というノードに当たり判定の設定をしていたが、これが原因で、物理演算に影響してしまっていた模様。
当たり判定は、”Area2D”というノードで設定する必要があった。
ポイント:Node2D と Area2D の違い
-
Node2D
- 2Dノードの基本クラス
- 位置(position)、回転(rotation)、スケール(scale)を持つ
- 当たり判定機能はない
- スプライトやその他の2Dノードをグループ化するための親ノードとして使用
-
Area2D
- CollisionObject2Dを継承(CollisionObject2DはNode2Dを継承)
- Node2Dの機能に加えて、当たり判定機能を持つ
- 他のボディやエリアとの重なりを検出できる
- body_entered、body_exited、area_enteredなどのシグナルを発行
- CollisionShape2D子ノードで当たり判定の形状を定義
- 物理演算には直接影響しない(検出のみ)
-
使い分け
- Node2D: 単純なグループ化や位置制御のみが必要な場合
- Area2D: アイテム取得、トリガーゾーン、敵の検出範囲など、何かが入ってきたことを検知したい場合
注意点
Node2Dは物理演算に影響してしまうみたい。
まとめ
この記事では、非ゲーム開発エンジニアが、Godotの開発でハマった部分について紹介しました。
知識や経験がなくても、AIの力を借りれば、実装自体はもりもりできます。
ですがやはり基礎の部分(今回でいうと物理エンジン等)への理解が浅いと、問題が発生した際、急に「ここはどこ?」という状態になってしまいます。
ひとつずつ、学べて行ければいいのだろうと思った。