投射物の発射
この記事は Godot 3から Godot 4 へ内容の書き換え中です。 Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリのIssuesまでご報告ください。
課題
プレイヤー/モブなどから投射物を発射させたい。
解決策
弾丸の設定
まず、インスタンス化可能な「弾丸」オブジェクトを設定します。使用するノードは以下の通りです。
Area2D: Bullet
Sprite2D
CollisionShape2D
Sprite2Dのテクスチャは、好きな画像を使用できます。以下は例です。
ノードの設定とスプライトおよび衝突判定形状を構成します。テクスチャが上向きに配置されている場合(上記例のように)は、Sprite ノードを 90° 回転させて右方向に向け、親オブジェクトの「前方」方向に一致するように調整してください。
スクリプトを追加し、Area2Dのbody_enteredシグナルに接続してください。
extends Area2D
var speed = 750
func _physics_process(delta):
position += transform.x * speed * delta
func _on_Bullet_body_entered(body):
if body.is_in_group("mobs"):
body.queue_free()
queue_free()
この例では、オブジェクトが何かを衝突した場合、即座に弾丸を除去します。また、「mobs」グループにタグ付けされた対象物もすべて削除します。
射撃
弾丸の出現位置を設定が必要です。Marker2Dコンポーネントを追加し、弾丸を出現させたい場所に配置してください。以下は具体例で、銃身の先端に設置しています。「Muzzle」という名前を付けています。
「プレイヤーが回転するにつれ、Muzzleのtransformは銃に対して常に同じ向きを保つことに注目してください。これは弾丸をスポーンさせる際に非常に便利です。変換行列を使用することで、適切な位置と方向を簡単に取得できるからです。新しい弾丸のtransformは、単にMuzzleのものと等しく設定するだけで済みます。
この手法は「回転・移動」スタイルに限らず、あらゆる文字タイプに適用できます。単に、弾丸を表示させたい位置に Marker2D タグを挿入するだけで済みます。
キャラクタースクリプト内で、インスタンス化用の弾丸シーンを保持する変数を追加してください。
@export var Bullet : PackedScene
入力アクションが定義されているか確認してください。
if Input.is_action_just_pressed("shoot"):
shoot()
これでshoot()関数内では、弾丸インスタンスを生成しツリーに追加できます。よくあるミスとして、プレイヤーノードの子要素として直接追加してしまうケースがあります
func shoot():
var b = Bullet.instantiate()
add_child(b)
b.transform = $Muzzle.transform
問題は、弾丸がプレイヤーの子オブジェクトであるため、プレイヤーが移動または回転した際に影響を受ける点です。
この問題を解決するには、弾丸をワールドに追加が必要です。ここではプレイヤーのシーンルートノードを参照する owner 変数を使います。ただし、銃口の グローバル 変換行列も適用する必要がある点に注意してください。これを行わないと、弾丸が想定した位置に表示されない可能性があります。
func shoot():
var b = Bullet.instantiate()
owner.add_child(b)
b.transform = $Muzzle.global_transform
関連レシピ
–>プロジェクトのダウンロード
プロジェクトコードはこちらからダウンロードできます。https://github.com/godotrecipes/2d_shooting