ゲームエンジンGodot4.0で3Dスマホゲームを作りたいと思いますが、その前にお勉強しています。
2023/3/1もstable版がリリースされました。おめでとうございます!
Godot_v4.0-stable_win64.exe.zipを使用しています。
目的
3Dの基本図形を組み合わせてキャラクターをデザインします。
またアニメーションも設定して動かします。
Bulletをデザインする
Playerが発射するもののデザインをします。発射するのは人っぽいものにしましょう。
ベースプロジェクト
下記で作成したプロジェクトをベースに機能追加をします。
【Godot 4.0】スマホ3Dゲームを作るための勉強 その11 敵も攻撃するようにしました
https://qiita.com/FootInGlow/items/885fd54f8f4992361e06
github(Godotのプロジェクトマネージャーからインポートして利用できます)
https://github.com/footinglow/Godot4/tree/main/02_study/S11_enemy_fire_002
新規でシーンを作成する
シーンメニューから新規シーンを実行します。
3Dシーンのボタンを押下してNode3Dを追加しましょう。名称を「DesignMySoldier」にします。
Ctrl-S等で保存しましょう。design_my_soldier.tscnという名称になると思います。
体と頭を追加する
DesignMySoldierの子ノードにMeshInstance3Dを追加して、「Body」に名称変更します。
Bodyの子ノードにMeshInstance3Dを追加して、「Head」に名称変更します。
-
Body(MeshInstance3D)にカプセル型を設定します。
インスペクタ内のMeshInstance3D/Meshを新規CapsuleMeshに設定します。
インスペクタ内のMeshInstance3D/Meshのアイコンをクリックして、Heightを1.5mにします。 -
Head(MeshInstance3D)に球型を設定します。
インスペクタ内のMeshInstance3D/Meshを新規SphereMeshに設定します。
インスペクタ内のNode3D/Transform/position/yを1.2mに設定します。
腕を追加する
腕を振るようにしたいので、肩(となるポイント)を追加して、その子として腕を追加します。
肩の回転のポイントはMarker3Dと使用するとエディター内で視認できるので便利です。
Bodyの子ノードとしてMarker3Dを追加します。「Shoulder_Right」に名称を変更します。
インスペクタ内のNode3D/Transform/position/xを0.7m、yを0.7mに設定します。
後面図で表示すると見やすいです。
Shoulder_Rightの子ノードとしてMeshInstance3Dを追加します。「Arm」に名称変更します。
Armを選択した状態で、インスペクタ内のMeshInstance3D/Meshを新規CapsuleMeshに設定します。
インスペクタ内のMeshInstance3D/Meshのアイコンをクリックして、Radiusを0.2m、Heightを1.0mにします。
インスペクタ内のNode3D/Transform/position/yを-0.5mに設定します。
右腕ができました。
次に左腕を作りましょう。
「Shoulder_Right」をコピーして、「Body」を右クリックして貼り付けをします。
「Shoulder_Right2」ができるので、「Shoulder_Left」に名称を変更します。
Shoulder_Leftを選択してインスペクタ内のNode3D/Transform/position/yを-0.7mに設定します。
左腕ができました。
両足を追加します。
腕をもとに右足を追加しましょう。
「Shoulder_Right」をコピーして、「Body」を右クリックして貼り付けをします。
「Shoulder_Right2」ができるので、「Hip_Right」に名称を変更します。
「Arm」は「Leg」に名称変更します。
Hip_Rightを選択してインスペクタ内のNode3D/Transform/positionのxに0.2m、yに-0.7mを設定します。
左足を追加します。
「Hip_Right」をコピーして、「Body」を右クリックして貼り付けをします。
「Hip_Right2」ができるので、「Hip_Left」に名称を変更します。
Hip_Leftを選択してインスペクタ内のNode3D/Transform/position/xを-0.2mに設定します。
Bulletのデザイン、DesignMySoldierが完成しました!
歩くアニメーションを追加する
歩かせましょう。
DesignMySoldierを右クリックから「子ノードを追加」して、AnimationPlayerを追加します。
AnimationPlayerには複数のアニメーションを登録することできます。「Walk」という名前で新規にアニメーションを追加しましょう。
AnimationPlayerノードを選択すると中央下部にアニメーション用のWindowsが表示されます。
中央の「アニメーション」メニューをクリックして、「新規」を実行します。
「Walk」と入力してOK押下します。
アニメーション名「Walk」の編集画面です。横軸は時間です。右のほうに「1」とあるのは1秒のアニメーションという意味になります。
まずは右肩を回転することで、右腕を振るように見えるアニメーションを最初に動かしましょう。
トラックを追加ボタンを押下して「プロパティトラック」を選択します。
右肩であるShoulder_Rightを選択します。
右肩Shoulder_Rightのプロパティのうちアニメーションで変更可能な一覧が表示されます。
回転したいので、rotationを選択してOKします。
「Shoulder_Right」のrotationがトラックに追加されました。
歩くアニメーションは自動で再生して、歩いている間はずっと腕をふりつづけたいです。
また右手を後ろから前にふって、前から後ろに戻すまで2秒にしたいと思います。
下記のように設定します。
・読み込み後自動再生をON(クリックして青にする)
・アニメーションループを有効(クリックして青にする)
・アニメーションの長さを2秒
次にキーポイントを追加します。アニメーションの長さを2秒に設定したので、0~2秒の時間軸上にキーポイントを作成して、そのときのrotationの値を設定します。キーポイントとキーポイントの間の値はGodotが自動で途中の値を計算してくれるのでとても便利です。
rotationの右側、0秒のあたりを右クリックして「キーを挿入」を実行します。
このようにキーを挿入したところにキーポイントを表す点が追加されます。
1秒のあたりにも右クリックしてキーポイントを追加しましょう。
0秒の時と1秒の時のrotationを設定しましょう。
まず0秒のキーポイントをクリックすると、インスペクタにキーポイントの情報が表示されます。Timeが0ピッタリではない場合0にします。xを-45°にします。
次に1秒のキーポイントをクリックします。
Timeを1.0にして、xは45°にします。
では動きを見てみましょう。
アニメーションウインドウ左上に、▶(右向き三角)のボタンを押下します。
右手をふっているでしょうか。
では同じ操作をShoulder_Left、Hip_Right、Hip_Leftにも行いましょう。
トラックを追加ボタンを押下して「プロパティトラック」を選択し、対象のノード(Shoulder_Left、Hip_Right、Hip_Left)を選択して、rotationを追加します。
キーポイントを0秒と1秒に追加しましょう。
rotation/xを下記のように設定します。右腕と左腕は逆、右腕、右足は逆にふるようにします。
ノート | 0秒の時のrotation/xの値 | 1秒の時のrotation/xの値 |
---|---|---|
Shoulder_Right | -45° | 45° |
Shoulder_Left | 45° | -45° |
Hip_Right | 45° | -45° |
Hip_Left | -45° | 45° |
実行しましょう。
右腕と左腕は交互に動いているか確認しましょう。
右腕と右足、左腕と左足が交互に動いている確認しましょう。
次の作業に入る前に保存します。
Bulletにデザインを適用します。
Bullet.tscnに今作成したデザインを以下のいずれかの手順で適用しましょう。
Bullet.tscnを開いてから下記いずれかの手順でdesign_my_soldier.tscnを追加します。
・ファイルシステム内のdesign_my_soldier.tscnをBullet.tscn内のBulletノードにドラッグアンドドロップする
・Bulletを右クリックしてInstantiate Child Sceneを実行後design_my_soldier.tscnを選択
サイズ感があっていませんので縮小する必要があります。右側にあるのがもともとのBulletのサイズです。(比較できるように、X軸プラス方向に適当に移動しました。後で削除します)
DesignMySoldierを選択します。
インスペクタ内のNode3D/Transform/scale/xを0.2に設定します。
xを変更するとyとzも同じ値になりますね。
元のサイズ感と同じくらいになりました。
もともとあったMeshInstance3Dは不要になったので削除しましょう。
キャラクターはグローバル座標系のy=0に設定すると地面に立っているように設定します。
3D表示で左側面図等で表示すると地面に埋まっていますね。
Bulletを選択してNode3D/Transform/position/yを0.3mにしましょう。
CollisionShape3Dと大体同じ位置、同じ大きさになっていることを確認しましょう。
実行しましょう。
発射すると人が歩いていきます。
影をつけて立体的にします。
せっかくの戦士がのっぺりしているので、影をつけて立体的にしましょう。
global.tscnのDirectionalLight3Dを選択して、インスペクタのDirectionalLight3D/Light3D/Shadowをオンにします。
影がつきましたね。
影が長すぎるのでDirectionalLight3Dの向きを変更します。
DirectionalLight3Dを選択して、インスペクタ内のNode3D/Transform/rotationのxを-60°、yを50°に設定します。
戦うアニメーションを追加する
ひとつ戦うアニメーションを追加しましょう。
両腕を高く振り上げて、殴りつけるようにします。
Battleアニメーションを新規追加する
design_my_soldier.tscnを開いて、DesignMySoldierノードの子ノードのAnimationPlayerを選択すると、すでに作成したWalkのアニメーションが表示されます。
「アニメーション」ボタンを押下して、「新規」をクリックします。
新規アニメーション名は「Battle」にしましょう。
両肩をアニメーションするので、「+トラックを追加」から「Shoulder_Right」のrotationと「Shoulder_Left」rotationを追加します。
下記のように設定します。
・読み込み後自動再生はOFFのまま(アイコンの色が白がOFF、青がONです)
・アニメーションループを有効(クリックして青にする)
・アニメーションの長さを1秒
「Shoulder_Right」のrotationの右側0秒と0.5秒のところを右クリックして、「キーを挿入」しましょう。
「Shoulder_Left」rotationにも同様にキーポイントを追加します。
挿入したキーをクリックすると右側のインスペクタに詳細情報が表示されるのでそれぞれ以下のように設定しまします。
ノート | 0秒の時のrotation/xの値 | 0.5秒の時のrotation/xの値 |
---|---|---|
Shoulder_Right | 135° | 215° |
Shoulder_Left | 215° | 135° |
例えば、Shoulder_Rightの0.5秒のキーをクリックして下記のように設定します。
アニメーションの再生ボタン(▶)クリックして再生しましょう。
GDScriptでアニメーションを選択する
GDScriptでWalkアニメーションとBattleアニメーションを選択するようにします。
Battle中を判断するのは、Bullet.tscnのBulletノードにアタッチしたbullet.gd内で行いますが、アニメーションの設定はdesign_my_soldier.tscn内のスクリプトで実行する必要があるので、design_my_soldier.tscnのDesignMySoldierノードにスクリプトを追加して、アニメーション指示をするAPIを追加します。
design_my_soldier.tscnを開いて、DesignMySoldierノードを右クリックして、「スクリプトをアタッチ」します。
下記のようにアニメーションを実行するAPIを追加しましょう。
extends Node3D
func animation_play(name):
$AnimationPlayer.play(name)
- $AnimationPlayer.play(name)
play関数の引数nameに設定したアニメーション名のアニメーションを実行します。
次はBullet.gdを修正して、今追加したanimation_playメソッド呼ぶ処理を追加します。
「func _physics_process(delta):」メソッド内で衝突判定をした後、衝突した場合は、「battle_pos」に衝突位置が設定されるので、battle_posが設定されている場合はBattleアニメーションを再生して、そうではない場合は、Walkアニメーションを再生するようにします。
:
# HPが0になったら消える
if m_hp < 0:
queue_free()
# アニメーションの設定
if battle_pos:
$DesignMySoldier.animation_play("Battle")
else:
$DesignMySoldier.animation_play("Walk")
# バトル中の相手、センシングした敵の順に目標位置を設定する
if battle_pos:
:
実行しましょう。
最初歩いている人が、EnemyもしくはEnemyBulletに衝突すると戦いを始めます。
以上