ぬーぶのメモ帳

フリーゲームエンジン「Godot」でプログラム経験のない素人の備忘録 最近は色々な動作を考えて試すのが好き。

【Godot】RayCast2Dで障害物を押す

アクションゲームで良く使われるギミック 



アクションゲームを作る時、キャラクターが押して移動させる足場やスイッチまで物を移動させて仕掛けを作動させるようなギミックは定番だと思われます。

RigidBody2Dを使うとスクリプトはいりませんが物理演算の動きが好みではないので、今回はKinematicBody2DとRayCast2Dを使い個人的に満足する動作を得られました。

:これの前提条件として移動できる操作キャラクターを用意してください。

押し出す箱をを作る

今回はKinematicBody2Dでプレイヤーが押し出す物体をつくります。
理由はスクリプトmove_and_slide()が床への衝突計算を自動で行ってくれるので一番楽だと思われます。

このノードにグループ名を付けておくことも忘れないで下さい。

# 動く箱

var gravity := 1500.0
var velocity := Vector2(0, 0)
var speed = 100

func _physics_process(delta: float) -> void:

# velocityにmove_and_slideを代入すると床衝突の時に速度がリセットされる
	velocity.y += gravity * delta
	velocity = move_and_slide(velocity)

# RayCast2Dを使ってこの関数を実行させる
func move(direction) -> void:
	position += 3 * direction

※velocityにmove_and_slideを代入した場合

※velocityにmove_and_slideを代入しなかった場合

このように床の上でも落下速度がずっと加算される

RayCast2D

RayCast自体は壁の接触判定やセンサーなど柔軟に使えるノードのようです。
その接触判定を使い衝突した物体の関数を実行させて箱を動かしてみます。

操作キャラクターにRayCast2D追加すると矢印のノードが追加されます。
インスペクタータブのEnabledを有効にしないと箱は動てくれないので注意。

追加したRayCast2Dをスクリプトで制御します

# プレイヤーのスクリプト

onready var ray = $RayCast2D
# 左にキーを入力したらvector2(-1, 0) 右ならvector2(1, 0)になるよう設定を
var direction = vector2(0, 0)

# cast_toで矢印の向く先を変える
	ray.cast_to = direction * 20
# colliding で矢印が何かと衝突した際trueを返す
	if ray.is_colliding():
# get_collider で衝突した物体を取得する
		var collide = ray.get_collider()
# 取得したもののグループを判定
		if collide.is_in_group("box"):
# 判定が一致すると対象のmove関数を実行できる
# プレイヤー側も方向指定する関数directionを作成して左右への移動方向を共有させる
			collide.move(direction)

先ほど箱で設定したグループ名をスクリプトで指定することで、箱のスクリプトのmove関数(関数名は任意)を実行させる事ができます。
:グループを指定しないと別のオブジェクトに矢印が接触した時、move関数が存在していない為エラーになる。

コリジョン判定を表示してプレイヤーの動作テスト

cast_toの制御が上手くできていれば下のように矢印が左右を向いてくれる

完成

最後に箱とプレイヤーを設置して動作を確認
上手く動いてくれない場合は箱のスクリプトis_on_floor()の条件で床に面してる時は重力を0にするなどの工夫をしてください。

スイッチギミックを作る際はスイッチにも箱のグループ名を指定する必要があります。
またはグループ名でなくコリジョンマスクでも可能なので好きな方法で当たり判定を指定するといいのではないでしょうか。