単純にボール同士が接触したときの当たり判定を取るつもりがなんかうまく行かなかったのでその時のメモ書き。
RigidBody2D同士の衝突検出をスクリプトでやる
Godot3までは設定がなかったのか、負荷軽減のためなのか当たり判定を検出するためにいくつか設定を追加する必要があります。表示上当たり判定しているのだからスクリプトでも取れるもんだと思ってました
やれること
同じ球体を落下させて、ぶつかったらスクリプトでプリントを出せるようにする。当たった!の文字は動画編集です。
おまけとして相手側のノードにスクリプトがついているかどうかも判定できるようにします。
キーワード
ここで特筆すべき機能などのキーワード。下記見て思い出せたら自分でやってみよう。
- RigidBody2D
- Max Contacts Reported
- Contact Monitor
- class_name
- is クラスのタイプ
当たり判定を取る下準備
以下は当たり判定を取るまでの手順。今回重要になるポイント以外に関しては簡略化してる部分もあります。ごめんね。
床を作る
新しいシーン「Floor」を作成します。
- StaticBody2Dをルートノードに設定
- MeshInstance2Dを追加
- QuadMeshを設定
- 画面の下部にボールを受けられるようないちに設定
- CollisionShape2Dを追加
- 形をRectangle Shape 2D
- MeshInstance2Dと重なるように当たり判定を調整
Ballシーンを作る
まずは地面に衝突するボールを作ります。
- Ballシーンを作成
- ルートノードにはRigidBody2Dを選択
- 表示用のノードを追加
- 画像素材がない場合MeshInstance2Dを追加
- MeshにはSphereMeshを利用してください
- 画像がある場合はSprite2Dと利用したい画像
- CollisionShape2Dを追加
- 円形のものを想定して話を進めます。Box(Rectangleでもいいですよ)
- ShapeにCircleを指定
- 表示用の大きさと当たり判定の大きさを合わせる
FloorシーンにBallを追加する
フロアシーンにボールを追加して、実行時に床の上にボールが乗るところまでやってみましょう。
- フロアシーンを開く
- ボールシーンを追加
- シーンのリンクマークもしくはCtrl+Shift+A からBall.tscnを選択する
- 位置を調整
- 追加されたボールを床の中央上部に移動させる
- 実行して(F6)ボールが落下して床で止まれば成功です。
床とぶつかったのを知る
では、上記のシーンを使って、ボール目線でなにかにぶつかったときにログを出してみたいと思います。今回だと床との当たったタイミングでログを出します。
ボールシーンにスクリプトを追加
ボールシーンのルートノード(RigidBody2Dがアタッチされているノード)を選択した状態で、スクリプトを作成します。デフォルトだとball.gdがくっつくはず。(下図はシグナル先につけてしまってるので少しだけ表示違うと思います)
シグナルを接続
RigidBody2Dがあるノードを選択した状態でインスペクターウインドのタブ違いからノードタブへ切り替えて_body_enterdシグナルを選択してから右下の接続ボタンを押してください。
接続後はball.gdをセットしたノードを選択して、ポップアップされたダイアログのまま接続を行います。
するとスクリプトにシグナル接続用のスクリプトが追加されます。
スクリプト編集
ここでやっとこスクリプト編集。今回は衝突時のみで良いので、下のように変更します
extends RigidBody2D
func _on_body_entered(body):
print("hit any")
RigidBody2Dのインスペクタ変更
ここがハイライトかもしれない。バージョン4から処理負荷軽減のためなのか、当たり判定を取るための処理は設定を入れなければスクリプトで知ることができなくなったみたいです。
- Max Contacts Reported:8
- ここの数字は1でも一応大丈夫ですが、同時に接触したときの報告数に制限がかかります。一気に多くの当たり判定を取得する場合、数値を変更してください。
- Contact Monitor:チェックを入れる
動かしてみる
あとはフロアシーンを動かしてみて、床にぶつかるとコンソールにhit anyが表示されたら成功です。
ボール同士が当たったかどうかを知る
ここからはおまけというか本題というか・・・。自分はこれを解決するついでに上の基本当たり判定をついでにまとめてました。
やりたいこと
スイカゲームのように、同じ種類のオブジェクトと当たったときのみアクションを起こしたい場合、上記のプログラムでは床だろうが別のフルーツだろうがお構い無しでアクションを起こしてしまいます。
ということで、ここからはボール同士が当たったのを検出したいと思います。
スクリプト変更
といってもスクリプト変更だけで対応できるのでそこまで重たい作業ではない。
extends RigidBody2D
class_name Ball
func _on_body_entered(body):
if body is Ball:
print("ボールと当たった")
else :
print("何かと当たったが、ボールではない")
当たった時の相手側bodyがBallという型を持っているかどうかを調べます。ボールの場合、今回はログしか出していませんが、ボールのメンバ変数にもアクセスできるため、パラメータ情報を見て判断させることもできるようになります。
確認するには
先程の床にボールを追加したシーンに、もう一つボールを追加してください。あとは落下軌道上にボールが重なるようにしておけば、ボール同士が当たった時と床が当たった時に異なるログが表示されます。
2倍ログが表示されますが、各ボール同士のログが表示されますのでご注意くださいませ。
コメント