0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Godot 4でGPUParticles2Dを使った魔法エフェクト: 3つの実装テクニック

0
Posted at

Godot 4 で 2D ゲームの「魔法エフェクト」を作るとき、AnimationPlayer でスプライトをパラパラ漫画する方法で済ませがちです。けれどパーティクルを使えば、同じ作業時間で 10 倍リッチに見えるエフェクトが作れます。

この記事では GPUParticles2D を使った魔法エフェクトの実装テクニックを 3 つ紹介します。コードは Godot 4.4 以降で動作確認済みです。

前提: GPUParticles2D の基本

GPUParticles2D は GPU 上でパーティクルを処理するノードです。CPUParticles2D より 10〜100 倍速いので、数千個のパーティクルでも 60FPS を維持できます。

最小構成はこれだけ:

# シーン構造
GPUParticles2D
└── ProcessMaterial: ParticleProcessMaterial
└── Texture: 32x32 の白い円

エディタ上で GPUParticles2D ノードを追加し、ProcessMaterialNew ParticleProcessMaterial を作成、Texture にパーティクルの形を設定すれば動きます。

テクニック 1: 火の玉エフェクト(放射状の上昇パーティクル)

魔法といえば火の玉。基本は「下から上に放出 + ランダムな広がり」です。

extends GPUParticles2D

func _ready():
    amount = 50
    lifetime = 1.0
    one_shot = false

    var mat = ProcessMaterial.new()

    # 上方向に放出
    mat.direction = Vector3(0, -1, 0)
    mat.spread = 30.0  # 30度の広がり

    # 速度
    mat.initial_velocity_min = 80.0
    mat.initial_velocity_max = 120.0

    # 重力で減速
    mat.gravity = Vector3(0, 50, 0)

    # 色: 黄→赤→透明
    var grad = Gradient.new()
    grad.add_point(0.0, Color(1, 1, 0.4, 1))
    grad.add_point(0.5, Color(1, 0.4, 0.0, 1))
    grad.add_point(1.0, Color(0.5, 0, 0, 0))
    mat.color_ramp = GradientTexture1D.new()
    mat.color_ramp.gradient = grad

    process_material = mat

ポイントは color_rampscale_curve の組み合わせです。色をパーティクルのライフタイムに沿ってグラデーションさせると、火炎独特の「黄から赤に冷えていく」感じが出ます。

テクニック 2: 回復オーラ(円形に内向きに集まるパーティクル)

回復系の魔法は「外から中心に集まる」動きが定番です。emission_shapeEMISSION_SHAPE_RING にして、初速をマイナスに設定すれば実現できます。

mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_RING
mat.emission_ring_radius = 80.0
mat.emission_ring_inner_radius = 70.0
mat.emission_ring_height = 0.0  # 2D なので 0
mat.emission_ring_axis = Vector3(0, 0, 1)

# 初速をマイナスにして中心に向かう
mat.initial_velocity_min = -60.0
mat.initial_velocity_max = -100.0

mat.flatness = 1.0  # 2D 平面に固定

# 色: 緑のグロー
var grad = Gradient.new()
grad.add_point(0.0, Color(0.4, 1.0, 0.4, 0))
grad.add_point(0.3, Color(0.4, 1.0, 0.4, 1))
grad.add_point(1.0, Color(0.8, 1.0, 0.8, 0))
mat.color_ramp = GradientTexture1D.new()
mat.color_ramp.gradient = grad

EMISSION_SHAPE_RING は本来 3D 用ですが、emission_ring_height = 0 にすれば 2D 平面でも使えます。flatness = 1.0 を設定するのを忘れずに。

テクニック 3: 雷エフェクト(瞬間的な強発光 + 減衰)

雷は「短時間に大量のパーティクル + 強い発光」で表現します。one_shot = trueexplosiveness = 1.0 の組み合わせがポイント。

amount = 200          # 多めに
lifetime = 0.3        # 短い
one_shot = true       # 一回だけ
explosiveness = 1.0   # 全部同時に放出

var mat = ProcessMaterial.new()
mat.direction = Vector3(0, 0, 0)
mat.spread = 180.0    # 全方向

mat.initial_velocity_min = 200.0
mat.initial_velocity_max = 400.0

# 発光のために CanvasItemMaterial を別途設定
var canvas_mat = CanvasItemMaterial.new()
canvas_mat.blend_mode = CanvasItemMaterial.BLEND_MODE_ADD
material = canvas_mat

BLEND_MODE_ADD がポイントです。重なったパーティクルが加算合成されるので、ぶつかり合うところが白く飛んで「閃光」になります。

呼び出すときは:

$ThunderParticles.restart()  # 一瞬で全パーティクル放出

デバッグの罠: パーティクルが見えないときのチェックリスト

  1. emitting = true か? デフォルトは true ですが、コードで false にしていないか確認。
  2. texture が設定されているか? Texture が空だと何も描画されません。
  3. amount > 0 か? デフォルト 8 ですが、one_shot で 0 になることがあります。
  4. 画面外で発生していないか? position が (0,0) のままで親が画面外にあるパターン。
  5. local_coords の挙動。 false (デフォルト) だと親の transform を継承しません。

特に 5 番は重要で、プレイヤーキャラクターから魔法を発射するときは local_coords = false にして、発射時の position を保存しておく必要があります。

まとめ

GPUParticles2D は使い始めの学習コストはありますが、一度パターンを覚えると 10 分で見栄えするエフェクトが作れるようになります。今回紹介した 3 パターン:

エフェクト 主な設定 用途
火の玉 color_ramp + 上向き放出 攻撃魔法、トーチ
回復オーラ EMISSION_SHAPE_RING + 負の初速 回復、シールド
one_shot + explosiveness=1.0 + BLEND_MODE_ADD 爆発、ヒット、閃光

これらをベースに、テクスチャを変えたり色を変えたりするだけで、十数種類のエフェクトが作れます。

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?