2Dプロジェクト作成手順④:衝突処理(KinematicBody/StaticBody)
前回記事はこちら。
前回までは単純に画像を動かす方法を紹介したが、今回からいよいよゲームエンジン(物理エンジン)っぽいことをやっていく。
前回までの単純に座標を変える方法での動かし方だと、「ほかの物とぶつかったときに停止する」などの処理が面倒なことになる。
やってやれないことはないが、お互いの座標エリアがカブったことを条件にして関数を呼び出して。。。等の処理を作らないといけない。まぁ、昔はそうだったが今は物理エンジンのある令和の時代なので、そこは物理エンジンにお任せするのが得策である。
その際に必要となるのが、KinematicBody/StaticBody(今回は使用しないがRigidBody)になる。
これから新しいノードとGDScriptを作るため、まずは、Iconから前回までに作成したGDScriptを解除(デタッチ)する。
次にMainSceneに対し、子ノードを追加。なかなか階層が深いが、下記のKinematicBody2Dを追加する。
その後、作ったKinematicBody2Dの子ノードにCollisionShape2Dを追加する。
その後、前回までに使用してアイコンをKinematicBodyの子ノードへもっていく。
これで動く側(衝突する側)のノード追加はひとまず完了。
作りやすくするためにいったんIconの座標を原点(0,0)に移動しよう。Iconを選択して右のプロパティからNode2D->Transform->Positionから位置調整出来る。下記のリセットボタンをクリックすれば原点に戻せる。
次にこのKinamaticBodyの衝突エリア(いわゆる当たり判定のエリア)を設定する。CollisionShape2Dのノードを選択し、右のプロパティメニューからCollisionShape2D->Shapeを選択し、新規RectangleShape2Dを選択する。
そうすると、CollisionShape2Dに対し、衝突エリアが設定された。(赤点に囲まれた部分が衝突エリアである)
角の点を引っ張って画像のサイズと衝突エリアを合わせる。
その際、CollisionShapeの座標が原点からずれていないことを確認する。(ずれていると当たり判定もずれてしまう)
この状態までいったら、親ノードのKinematicBodyノードを選択したうえで下記アイコンをクリックして子ノードが選択できないようにする。こうすることで間違ってアイコンやCollisionShapeを選択してしまい位置がずれることを防ぐ。
上記まで終了したら、好きな位置まで戻そう。
さて、次は衝突される側である。
今度はStaticBody2Dというノードを追加する。CollisionShape2DやIconを子ノードに設定するやり方はKinematicBodyと同様である。
IconはひとまずGodot君を使おう。細長いGodot君の壁を作る。
そのうえで大体KinematicBodyの横の位置に配置。
そのうえでIconと同じようにKinematicBodyの座標を少しずつ動かして、、、とやると、なんとKinematicBodyは壁をすり抜けてしまう。
なぜかというと、あくまで上記のIcon時のやり方は簡易的にただ座標を動かしているだけだからである。
KinematicBodyの場合はmove_and_slideという関数を使用する。中に入れる値はVector2と呼ばれる値の型を入れる必要がある。
Vector2とは何ぞや?という感じかもしれないが、xとyのベクトルのことである。
下記のように書くと毎フレームごとにx=100,y=20のベクトル方向にCollisionShape2Dを動かすという処理になる。
これを実行すると、まず壁に向かって進んだ後に衝突する。その後、壁をつたってずるずると下に進み、壁がなくなった部分からまた右下へ抜けていく。(ちなみにVector2のyは下方向が+である。数学のxy座標に慣れていると間違えるので注意。)
次回はより現実の物理に近いRigidBodyを使用した動作を解説する。
(補足)RigidBody/KinematicBody/StaticBodyの違い
■RigidBody
ほぼ現実に存在する物と同じように重さや反発係数(壁に当たった時の跳ね返り方を調整するパラメータ。ゴムボールなら1に近く、金属なら0に違いイメージ。)を設定して、ほぼ現実世界に近い動きをする。
より、現実的な動きを物理エンジンで勝手にやってくれることが大きなメリットでもあるが、同時にデメリットでもある。(想定外の位置に跳ね返ったり落ちたりするなど)
■KinematicBody
衝突判定だけをしたい場合、必要な物理動作だけを定義してコントロールしたい場合にはKinematicBodyを使用する。
RigidBodyでは重さを設定すれば勝手に重力で落ちる動作は設定されるが、KinematicBodyでは個別に制御を自分で組む必要がある。
制御をいちいち組まなくてはいけない分だけ面倒ではあるが、その分想定外の動作が起きにくいというのはメリット。
■StaticBody
何も動かないもの使用する。極端なことを言えば、衝突されるためだけにあるもの。
壁など、動く可能性のないものに使用するのが一般的。
※もちろん動かすことは出来るが、わざわざStaticBodyを使用する理由がない。