【Godot】KinematicBody2Dの is_on_floor() と One wayコリジョンの使い方

この記事では KinemetaicBody2D is_on_floor() の使い方と、One way 床 (一方通行床) の使い方を解説します。

KinematicBody2D.is_on_floor() の使い方

KinematicBody2Dについて

KinematicBody2Dとは、物理エンジンで動作するノードでありながら、移動パラメータや移動タイミングをスクリプトで指定可能なオブジェクトなります。

物理エンジンで動作する2Dノードの比較は以下のとおりです。

ノード名物理エンジン
での制御
用途
RigidBody2D自動で動く物理制御のみで動く
ようなオブジェクト。
粒子やバネ、流体など
StaticBody2D物理制御するが
動かさない
オブジェクト
床や壁など、衝突したときに
動かないが物理制御したいオブジェクト。
スクリプトで動かすことも可能なので、
移動床なども可能
KinematicBody2Dスクリプトで
専用の物理関数を
呼び出すことで動く
スクリプトで細かく制御したい
物理オブジェクト。
プレイヤーキャラや敵キャラなど

RigidBody2DStaticBody2D は、基本的に物理シミュレーションで動くような Physics puzzle game (物理パズルゲーム)Sandbox game (サンドボックスゲーム) を作るのに向いています。

このあたりの使い方は以下の記事に書いていますので、興味があれば参考になるかもしれません。

【Godot】RigidBody2Dの基本的な使い方 【Godot】2D Jointの使い方

そしてKinematicBody2D の用途としては、主に 足場をジャンプで飛び移るアクションゲームの 2D Platformer (プラットフォーマー)Top-down (トップビュー) のようなゲームと相性が良いです。

Platformerの一例の
ラン&ジャンプゲーム
Top-down (見下ろし型) ゲーム

move_and_slide() を使って移動処理を行う

KinematicBody2Dノードには、move_and_slide() というとても便利な関数が用意されています。これを使用した最低限の移動とジャンプを実装したコードは以下のとおりです。

extends KinematicBody2D

const MOVE_SPEED = 50
const DECAY_MOVE_SPEED = 0.9 
const GRAVITY = 50
const JUMP_POWER = 1000

var _velocity = Vector2.ZERO # 速度ベクトル

func _physics_process(delta: float) -> void:
	# 重力を加算
	_velocity.y += GRAVITY
	
	# 移動量を減衰.
	_velocity.x *= DECAY_MOVE_SPEED
	
	# 左右移動.
	if Input.is_action_pressed("ui_left"):
		_velocity.x -= MOVE_SPEED # 左方向に移動
	elif Input.is_action_pressed("ui_right"):
		_velocity.x += MOVE_SPEED # 右方向に移動.
	
	# ジャンプ.
	if Input.is_action_just_pressed("ui_accept"):
		# SPACEキーでジャンプする.
		_velocity.y = -JUMP_POWER
	
	# 移動処理を行う
	_velocity = move_and_slide(_velocity)

このように、移動ベクトル _velocity の値を move_and_slide() に渡すことで、衝突応答と移動処理を簡単に実装することができます。

is_on_floor() の使い方

次にジャンプ中かどうかを判定する方法です。KinematicBody2D には is_on_floor() という便利関数が用意されていて、この関数で床の上に乗っているかどうかを簡単に判定できます。

ただ、is_on_floor() を使用するには、move_and_slide() の二番目の引数に床と判定する方向ベクトルを指定する必要があります。

	# ジャンプ.
	if _is_jumping == false:
		# ジャンプ中でなければジャンプできる.
		if Input.is_action_just_pressed("ui_accept"):
			# SPACEキーでジャンプする.
			_velocity.y = -JUMP_POWER
	
	# 移動処理.
	# ※第2引数に床と判定する方向ベクトルを渡す必要がある
	_velocity = move_and_slide(_velocity, Vector2.UP)
	
	if is_on_floor():
		_is_jumping = false # 床に着地している
	else:
		_is_jumping = true # ジャンプ中.

move_and_slide() の 二番目の引数に Vector2.UP を渡しています。これにより「上から衝突したら床とする」ということとなり、is_on_floor() が正常に動作するようになります。

One way床の使い方

2D Platformer (プラットフォーマー) を作る場合、通り抜けできない床は少し不便です。

通り抜けできない床

もちろんゲームデザイン上、そのような床があっても良いですが、通り抜け可能な床 (一方通行床) があるとステージ設計時に自由度が生まれます。

これを実装するのは簡単で、コリジョンの設定からOne Way Collision」の項目にチェックを入れるだけです。

ちなみに一方通行床にした場合は、エディタ上で矢印が表示されるようになります。

これで上からのみ衝突する床にすることができます。

完成プロジェクト

今回作成したプロジェクトファイルを添付しておきます。

タイルマップとの衝突

タイルマップとの衝突は以下の記事が参考になりそうです。

ジャンプと着地時にスケールする

以下はジャンプと着地を気持ちよくするためのスケールを入れたプロジェクトです。

参考