【Godot 4.0】スマホ３Dゲームを作るための勉強　その３０　敵の砦を倒した時のアニメーション

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

# 目的
　敵の砦を倒した後にただ消えるだけでは寂しいので、砦が倒れるアニメーションを追加します。
　敵の砦が消えるのと同時に、アニメーション用のシーンを生成するようにします。

# ベースプロジェクト
　下記で作成したプロジェクトをベースに機能追加をします。
　【Godot 4.0】スマホ３Dゲームを作るための勉強　その２９　ゲームの背景に空のテクスチャを貼ります
　https://qiita.com/FootInGlow/items/f7661fdeadb2dbcbdbdf
　
　github(Godotのプロジェクトマネージャーからインポートして利用できます）
　https://github.com/footinglow/Godot4/tree/main/02_study/S29Background
　※別途ダウンロードが必要です。
　　　res://assets/texture/godot-material-dpa-1.0.1/Readme.txt及び
　　　res://assets/texture/AllSkyFree1.0/Readme.txtを参照

# 敵の砦のアニメーション用シーンを作成する
# 敵の砦のアニメーションシーンを新規作成する
　シーンメニューの「新規シーン」を実行します。「3Dシーン」ボタンを押下するとNode3Dが追加されます。名称を「EnemyDefeatedAnimation」に変更します。
　保存します。
　保存ダイアログの右上の「フォルダーを作成」ボタンを押下します。
![スクリーンショット (419).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/2086d2ce-3c10-c848-b147-7889f6d57c88.png)
「Decorations」（飾り）フォルダを作成します。
![スクリーンショット (420).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/a2b544e9-f463-e37a-f609-98ecdc202f31.png)
　Decorationsフォルダに「enemy_defeated_animation.tscn」という名前で保存します。
![スクリーンショット (421).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/4f7f8271-f523-2a82-f751-1d8653c4ab5a.png)
　保存されました。
![スクリーンショット (422).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/ad68b6f6-c32c-4cbf-674f-6b31301fcbf0.png)

## 敵の砦のデザインシーンを追加する
　シーン内のルートノード「EnemyDefeatedAnimation」を右クリックして、「Instantiate Child Scene」を実行します。
「Design/design_enemy_fort.tscn」を開きます。
![スクリーンショット (423).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/462a4b51-ed19-acda-66fe-4ad1d1a251f3.png)
子ノードに「DesignEnemyFort」が追加されました。
![スクリーンショット (424).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/095ee55d-05c6-a994-434e-db41599a6f27.png)

　DesignEnemyFortを選択して、インスペクタのNode3D/Transform/Positionのyを0.5にします。
　res://Characters/enemy.tscnのDesignEnemyFortと同じ位置に設定しました。
　（改めてみると少し埋まっているのに気が付きました。正しくは0.75mですが、今まで0.5mで説明してきたので0.5mとします）
![スクリーンショット (447).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/cf898188-a777-6744-8e5c-08b0c4186da4.png)

## AnimationPlayerを追加・設定する
　シーン内のルートノード「EnemyDefeatedAnimation」を右クリックして、子ノードを追加からAnimationPlayerを追加します。
![スクリーンショット (425).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/a9891464-2fd6-3c78-862d-242fabad6af8.png)

　倒した敵の砦は沈み込みながら、倒れるようにします。
　沈み込むのはpositionのyをマイナスに移動します。倒れるのは、Rotationのzを操作してZ軸周りを90°回転するようにします。　

　画面下部の「アニメーション」メニューをクリックして、「新規」を実行します。
![スクリーンショット (426).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/640eb2a1-6c33-a5c0-5731-77394d40c711.png)
　「Defeated」という名前で追加します。

　次に「＋トラックを追加」をクリックして「プロパティトラック」を選択します。
![スクリーンショット (428).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/42a47def-1964-33c9-ca71-2ad9e53a8df1.png)
　回転対象としてDesignEnemyFortを選択します。
![スクリーンショット (429).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/51507612-73d5-d2fb-cec5-0d727ad996e1.png)
　rotationを選択します。
![スクリーンショット (430).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/dfede713-ea5b-7f2b-49a4-e333cd2a9aa5.png)

　同様に、「＋トラックを追加」をクリックして「プロパティトラック」を選択して、移動対象としてDesignEnemyFortのPositinを選択します。
　アニメーションの長さ（秒）は2秒にします。
![スクリーンショット (434).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/4a0e6e23-4f7a-edfb-8629-f15ae4bbfeb7.png)

　rotationの右、0秒のあたりを右クリックして「キーを挿入」します。2秒のあたりにもキーを挿入します。
　同様に、positionの0秒と2秒のあたりにもキーを挿入します。


　追加したキーをクリックすると、右側のインスペクタで値を設定することができますので、それぞれ下記の表のように設定します。

| 項目名 | Time | 設定値 |
|:-:|:-:|:-:|
|rotation|0.0|(x,y,z)=(　0°,　0°,　0°　)|
|rotation|2.0|(x,y,z)=(　0°,　0°,　90°　)|
|position|0.0|(x,y,z)=(　0m,　0.5m,　0m　)|
|position|2.0|(x,y,z)=(　0m,　-0.5m,　0m　)|

　再生ボタンを押下して、アニメーションを実行して確認します。
![スクリーンショット (450).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/2bf6c066-cc21-b105-5d24-24bfb952f9dd.png)
　
　アニメーション開始時(Time=0.0秒）
![スクリーンショット (448).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/829d3dfc-5263-7ab9-bb19-55eabe4a0884.png)

　アニメーション終了時(Time=2.0)
![スクリーンショット (449).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/e3751723-83f1-19fe-ae53-d38319d71a40.png)

# EnemyDefeatedAnimationのAPIを作成
　ルートノードの「EnemyDefeatedAnimation」を右クリックして「スクリプトをアタッチ」を実行します。
![スクリーンショット (437).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/1ba82a32-5d0d-ee3a-42c6-88f9ce171335.png)
　res://Decorations/enemy_defeated_animation.gdとして作成します。
![スクリーンショット (438).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/8a63c5c3-1d49-8aa7-5c9d-b2c884cfbc58.png)

　アニメーションを実行するAPIを実装します。
```GDScript
extends Node3D

func animation_play(name):
	$AnimationPlayer.play(name)
```
　次にアニメーションが完了したときにEmitされるシグナルを利用して自身を削除するようにします。
　AnimationPlayerを選択した状態で、インスペクタの横のノード/シグナルをクリックします。
AnimationPlayer/animation_finished(anim_name:StringName)を右クリックして、「接続」を実行します。
![スクリーンショット (439).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/acd91d01-53cb-9783-9743-e22cf3d21225.png)
「EnemyDefeatedAnimation」を選択します。
　![スクリーンショット (440).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/33b836fc-963e-42c8-cbe3-93886faf01f5.png)
「func _on_animation_player_animation_finished(anim_name):」が追加されました。
　アニメーション終了時に呼び出されるので自身を削除するように修正します。
```GDScript
extends Node3D

func animation_play(name):
	$AnimationPlayer.play(name)

func _on_animation_player_animation_finished(anim_name):
	queue_free()
```

# 倒された敵の砦が消えるときに、EnemyDefeatedAnimationシーンを生成する。
　敵の砦のスクリプトの中でhpが0未満になった場合に消える処理の前に、EnemyDefeatedAnimationシーンの生成処理を追加します。
　res://Characters/Enemy.gdを開きます。

　メンバ変数にPackedSceneを宣言して@exportします。
```GDScript
@export var m_scn_enemyDefeatedAnim : PackedScene
```
　スクリプトを保存します。
　res://Characters/enemy.tscnを開いて、ルートノードのEnemyを選択してインスペクタを確認すると、「Enemy.gd/M Scn Enemy Defeated Anim」が追加されています。
　＜空＞の右の「ｖ」アイコンをクリックしてクイックロードを実行します。
![スクリーンショット (441).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/a5abdad5-54a3-8c2c-23ea-0ec6f5992bc3.png)
　「Decorations/enemy_defeated_animation.tscn」を開きます。
　![スクリーンショット (442).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/ac286443-a952-6d8c-b045-e0e36b38cddd.png)
　「EnemyDefeatedAnimation」シーンを設定しました。
![スクリーンショット (443).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/fa14a549-9973-8c94-e76e-501fa49ec250.png)

　次に、敵の砦シーンを消す前に、EnemyDefeatedAnimationシーンを生成します。
　res://Characters/Enemy.gdの「_physics_process」メソッドを下記のように修正します。
```GDScript
func _physics_process(delta):
	if m_hp < 0.0:
		var ins = m_scn_enemyDefeatedAnim.instantiate()
		ins.transform.origin = transform.origin
		add_sibling(ins)
		ins.animation_play("Defeated")
		queue_free()
```

* **var ins = m_scn_enemyDefeatedAnim.instantiate()**
　先ほど登録したEnemyDefeatedAnimationシーンを生成します。
* **ins.transform.origin = transform.origin**
　表示位置をEnemyと同じ位置に設定します。
* **add_sibling(ins)**
　生成したシーンをEnemyと同じ階層に追加します。
* **ins.animation_play("Defeated")**
　Defeatedアニメーションの実行を開始します。
* **queue_free()**
　倒されたEnemyシーンを削除依頼します。

# 実行
　敵の砦が沈みつつ倒れるようになりました。
![スクリーンショット (446).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691050/4ce80fe6-7c30-d762-43fe-146bd81bde91.png)

　以上です。