0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Godot 4.0】スマホ3Dゲームを作るための勉強 その6 CharacterBody3Dを動かしましょう

Posted at

ゲームエンジンGodot4.0で3Dスマホゲームを作りたいと思いますが、その前にお勉強しています。
Godot_v4.0-rc1_win64.exe.zipを使用しています。

目的

 CharacterBody3Dを動かしましょう。

CharacterBody3Dを動かす

 新規プロジェクトを作成して下記のようになるようにノードを追加しましょう。
 ルートノードはNode3Dで、名称をglobalに変更しています。

 (_) global.tscn - S06_CharacterBody3D_Control - Godot Engine 2023_02_24 11_39_46.png

  1. Camera3Dはトップビューにします。上から見下ろす感じです。
      インスペクタ内のNode3D/Transform/position/x,y,z に0.0m, 5.0m, -1.0mを設定
      インスペクタ内のNode3D/Transform/rotation/xに-90°を設定
  2. MeshInstance3Dにカプセル型を設定します。
      インスペクタ内のMeshInstance3D/Meshを新規CapsuleMeshに設定します。
  3. CollisionShape3Dに衝突形状を設定
      MeshInstance3Dと同じ形にします。
      インスペクタ内のCollisionShape3D/Shapeに新規CapsuleShape3Dを設定
  4. 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/の速度で動いていると思います。

Screenshot 2023_02_24 13_54_12.png

CharacterBody3Dが衝突する時の動作

 CharacterBody3Dが進む先に障害物としてStaticBody3Dを置きます。
 
「【Godot 4.0】スマホ3Dゲームを作るための勉強 その6」を編集 - Qiita - Google Chrome 2023_02_24 13_57_45.png

  1. 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°を設定 
    global.tscn - S06_CharacterBody3D_Control - Godot Engine 2023_02_24 23_28_26.png

  2. MeshInstance3Dにboxを設定します。
      インスペクタ内のMeshInstance3D/Meshを新規BoxMeshに設定します。

  3. CollisionShape3Dに衝突形状を設定
      MeshInstance3Dと同じ形にします。
      インスペクタ内のCollisionShape3D/Shapeに新規BoxShape3Dを設定

 ビューメニューから2ビューポートを選択しています。camera3Dを選択した状態で下のビューポートのプレビューのプレビューをチェックすると実行時の構図を確認することができます。
(_) global.tscn - S06_CharacterBody3D_Control - Godot Engine 2023_02_24 14_03_32.png

 実行します。
 衝突すると、障害物にそって斜めに進みます。
「【Godot 4.0】スマホ3Dゲームを作るための勉強 その6」を編集 - Qiita - Google Chrome 2023_02_24 14_05_09.png

障害物がなくなると、前方(Z軸マイナス方向)に進みます。
S06_CharacterBody3D_Control (DEBUG) 2023_02_24 14_05_11.png

障害物をよけた後に、前方に進むのは、_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で衝突面に反発するような速度を取得します。
     

以上

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?