ゲームエンジンGodot4.0で3Dスマホゲームを作りたいと思いますが、その前にお勉強しています。
Godot_v4.0-rc1_win64.exe.zipを使用しています。
目的
CharacterBody3Dを動かしましょう。
CharacterBody3Dを動かす
新規プロジェクトを作成して下記のようになるようにノードを追加しましょう。
ルートノードはNode3Dで、名称をglobalに変更しています。
- Camera3Dはトップビューにします。上から見下ろす感じです。
インスペクタ内のNode3D/Transform/position/x,y,z に0.0m, 5.0m, -1.0mを設定
インスペクタ内のNode3D/Transform/rotation/xに-90°を設定 - MeshInstance3Dにカプセル型を設定します。
インスペクタ内のMeshInstance3D/Meshを新規CapsuleMeshに設定します。 - CollisionShape3Dに衝突形状を設定
MeshInstance3Dと同じ形にします。
インスペクタ内のCollisionShape3D/Shapeに新規CapsuleShape3Dを設定 - DirectionalLight3Dをほかのノードと重ならないように移動
x=-10に変更しました※。
※DirectionalLight3Dは3D空間の中のどこにあってもよいのですが、中央にあると邪魔なので移動しています。
シーン内のCharacterBody3Dを右クリックし、スクリプトをアタッチします。
スクリプト全体を下記のように書き換えましょう。
extends CharacterBody3D
func _physics_process(delta):
velocity = Vector3(0.0, 0.0, -1.0).normalized()
move_and_slide()
- extends CharacterBody3D
CharacterBody3Dを継承しましょう。 - func _physics_process(delta):
_processではなく、_physics_processメソッドを使用します。
物理エンジンの演算結果(現在位置、向き、速度など)を使用するまたは、動きの指示をする場合は、_physics_processメソッドの中で実行しましょう。 - velocity = Vector3(0.0, 0.0, -1.0).normalized()
速度を設定します。単位はm/sです。 - move_and_slide()
設定した速度でノードを動かすように物理エンジンに依頼します。
衝突なので速度に変化があった場合、velocityが上書きされます
実行しましょう。1ms/の速度で動いていると思います。
CharacterBody3Dが衝突する時の動作
CharacterBody3Dが進む先に障害物としてStaticBody3Dを置きます。
-
StaticBody3Dの立方体の角がCharacterBody3Dに衝突するように回転します
インスペクタ内のNode3D/Transform/position/x,y,z に0.0m, 0.0m, -3.0mを設定
インスペクタ内のNode3D/Transform/rotation/x,y,z に0.0°,-40°,0.0°を設定
-
MeshInstance3Dにboxを設定します。
インスペクタ内のMeshInstance3D/Meshを新規BoxMeshに設定します。 -
CollisionShape3Dに衝突形状を設定
MeshInstance3Dと同じ形にします。
インスペクタ内のCollisionShape3D/Shapeに新規BoxShape3Dを設定
ビューメニューから2ビューポートを選択しています。camera3Dを選択した状態で下のビューポートのプレビューのプレビューをチェックすると実行時の構図を確認することができます。
障害物をよけた後に、前方に進むのは、_physics_processメソッドの中で、Vector3(0.0, 0.0, -1.0)を毎回設定指示しているためです。
下記のようにvelocityは初期化時に1回のみ設定するようにしてみましょう。
またvelocityをprintします。
extends CharacterBody3D
func _ready():
velocity = Vector3(0.0, 0.0, -1.0).normalized()
func _physics_process(delta):
move_and_slide()
print(velocity)
- func _ready():
初期化時に1回のみ実行されるので、velocityも1回だけVector3(0.0, 0.0, -1.0).normalized()にします。 - move_and_slide()
物理エンジンにより、衝突などにより変更した速度がvelocityに反映されます。
衝突した瞬間にVelocityが物理エンジンによって書き換えられました。
:
(0, 0, -1)
(0, 0, -1)
(0, 0, -1)
(0.122316, 0, -0.015192)
(0.122316, 0, -0.015192)
(0.122316, 0, -0.015192)
:
move_and_collideで移動する
move_and_slideメソッドは便利ですが、衝突したときの動きを実装したい場合、move_and_collideを使用します。
extends CharacterBody3D
var m_velocity = Vector3(0.0, 0.0, -1.0)
func _physics_process(delta):
move_and_collide(m_velocity.normalized() * delta)
- move_and_collide(m_velocity.normalized() * delta)
move_and_collideの場合は、引数に経過時間(delta)あたりの移動量を設定します。
実行すると、衝突すると停止します。
下記のようにすると、衝突したときに反発するようにできます。
extends CharacterBody3D
func _ready():
velocity = Vector3(0.0, 0.0, -1.0)
func _physics_process(delta):
var collision_info = move_and_collide(velocity.normalized() * delta)
if collision_info:
velocity = velocity.bounce(collision_info.get_normal())
- var collision_info = move_and_collide(velocity.normalized() * delta)
衝突情報としてKinematicCollision3Dデータが返却されます。 - if collision_info:
衝突した場合collision_infoには何か設定されるのでtrueになります。 - velocity = velocity.bounce(collision_info.get_normal())
collision_info.get_normal()で衝突面(の法線)を取得します。normalized(正規化)とは別物です
velocity.bounceで衝突面に反発するような速度を取得します。
以上