今回はCharacterBody2D、RigidBody2D、それらに必要なCollisionShape2Dの3つをまとめて触ってみました。CharacterBody2DとRigidBody2Dは、どちらもゲームの中で「動くもの」を作るためのノードです。どちらも当たり判定の形を決めるCollisionShape2Dとセットで使うノードなので、3つ一緒に確かめるのがちょうどいいと思いました。
大きな違いは、RigidBody2Dは置いておくだけで重力で勝手に落ちていき、CharacterBody2Dはスクリプトで指示しない限りその場から動かなかったというところでしょうか。プレイヤーキャラクターのように自分で操作したいものはCharacterBody2D、箱やボールのように物理法則に任せて動かしたいものはRigidBody2D、という使い分けになりそうです。
まずはシーンにCharacterBody2DとRigidBody2Dを追加してみました。すると、どちらのノードにもすぐに黄色い警告マークが付きました。

警告マークにマウスを乗せると、「このノードにはシェイプがないため、他のオブジェクトと衝突または相互作用することはできません」と表示されます。CollisionShape2DかCollisionPolygon2Dを子として追加するように、というところまで案内してくれるので、次に何をすればいいのかは迷いません。RigidBody2Dにも同じ警告が出ていました。こういう、次に何が必要かを示してくれるのは親切だと思う一方、警告マークは不安にさせますね。最初から設定しておいてと思う人もいそうですが、選択肢があるものだとそうもいかない、というところでしょうか。
CollisionShape2DかCollisionPolygon2Dを必要とするということは、見た目を担当するSprite2Dとは別に、ぶつかる形を担当するノードを付ける必要がある、ということですね。Sprite2Dの画像がどれだけ大きくても、それ自体は当たり判定になりません。見た目と当たり判定が分かれていれば、たとえばキャラクターの髪の毛の先には当たり判定を付けない、といった調整もしやすくなります。別々のノードになっているのは理にかなっていると感じました。今回は触れていませんが、CollisionShape2Dは四角や楕円などあらかじめ決まった形があり、CollisionPolygon2Dは自分で形を決められるもののようです。キャラが持つ武器など、複雑な形の場合はCollisionPolygon2Dがよさそうですかね。
とりあえず、警告文に従ってCharacterBody2DにCollisionShape2Dを追加してみました。

追加した直後は、今度はCollisionShape2Dのほうに警告マークが移りました。親のCharacterBody2Dの警告は消えましたが、CollisionShape2DのShape欄が「<空>」のままなので、形を決めないと使えない、ということのようです。これも、とりあえず何らかの形を入れていてくれた方が、ユーザーは形を変えたくなった時に変え方を探すと思うんですけどね。警告やめて~と思うのは慣れるまでかもしれませんけど。
CollisionShape2DのShape欄のプルダウンを開くと、WorldBoundaryShape2D、SegmentShape2D、SeparationRayShape2D、CircleShape2D、RectangleShape2D、CapsuleShape2D、ConvexPolygonShape2D、ConcavePolygonShape2Dの8種類が並んでいました。名前から考えると、ボールならCircle、箱ならRectangle、人型のキャラクターなら角のないCapsuleあたりを選ぶことになりそうです。今回はアイコンの画像に合わせて、両方ともRectangleShape2Dを選びました。
床にはStaticBody2Dを置き、同じようにCollisionShape2Dで横長の四角を付けました。StaticBody2Dは動かない物体用のノードで、今回は床の役として使っています。最終的なシーンの構成はこうなりました。

なお、実行中も当たり判定の形が見えるように、メニューの「デバッグ」から「コリジョン形状を表示」をオンにしています。これをオンにすると、実行画面でも床が水色の四角で表示されます。見た目と当たり判定がずれていないかをテストプレイで確認するときに便利そうです。
まずはスクリプトを何も付けずに実行してみます。

実行した瞬間、右のRigidBody2Dだけがストンと落ちて床の上に乗りました。左のCharacterBody2Dは、置いた位置からまったく動きません。同じように当たり判定を付けていても、重力が効くかどうかがここまで違うのは意外でした。
RigidBody2Dは、重力や衝突といった物理の計算をGodotに任せるノードです。自分で何も書かなくても落ちて床に止まってくれるので、崩れる積み木や転がる岩のように「自然に動いてほしいもの」を置くのに向いていそうです。
一方でCharacterBody2Dは、スクリプトで動かすことが前提のノードです。何もしなければ動かないのは不便にも見えますが、プレイヤーキャラクターがほかの物体に押されて勝手にずれていったら、操作しづらくて仕方ありません。ボタンを押したときだけ思い通りに動いてほしいキャラクター用だからこそ、デフォルトでは何もしないようになっているのだと思います。
では、CharacterBody2Dを動かすにはどうすればいいのか。スクリプトをアタッチする画面を開くと、テンプレートに「CharacterBody2D: Basic Movement」という項目がありました。

説明には「Classic movement for gravity games (platformer, …)」と書かれていて、横スクロールのアクションゲームのような、重力のあるゲーム向けの基本的な動きが入ったテンプレートのようです。今回はコードを一切書き換えずに、そのまま作成して実行してみました。
実行すると、今度はCharacterBody2Dも下に落ちて、床の上に着地しました。矢印キーの左右で横に移動することもできます。コードを書かなくても、テンプレートを選ぶだけで最低限動くキャラクターになるのはありがたいですね。とりあえず動くものを作ってから、あとで少しずつ調整していく、という進め方がしやすそうです。
せっかくなので、CharacterBody2Dを右に動かして、隣のRigidBody2Dにぶつけてみました。

結果は、押せるようなこともなく、止まりました。CharacterBody2DはRigidBody2Dの手前で壁にぶつかったように止まり、RigidBody2Dもその場から動きません。
最初は、四角い形同士なので転がらずに止まったのかと思いました。ところが調べてみると、Godot 4のCharacterBody2Dは、ぶつかった相手に力を加えない仕組みになっているようです。RigidBody2Dを押したい場合は、ぶつかったときにスクリプトで力を加える処理を自分で書く必要があるそうです。パズルゲームの「押して動かす箱」のようなものを作りたいときは、ここを知っておかないと悩みそうです。倉庫番とか好きだったので。
3つを触ってみて、CollisionShape2Dは「ぶつかる形」、CharacterBody2Dは「自分で動かす体」、RigidBody2Dは「物理に任せる体」と整理すると分かりやすいと感じました。どちらのBodyを選ぶかで、自分でキャラクターを動かすのか、Godotに動かしてもらうのかが決まる、というイメージです。アクションゲームなら、プレイヤーはCharacterBody2D、落ちてくる岩や転がるボールはRigidBody2D、床や壁はStaticBody2D、という組み合わせが基本になりそうです。



コメント