GodotにEffekseerを導入して、発射エフェクトを実装する

Godot Engine Advent Calendar 2024の2日目の記事です

本記事では以下について解説します。

  • GodotのプロジェクトにEffekseerのプラグインを導入する手順
  • エフェクトの素材を改造してゲームに組み込む方法

こんな発射エフェクトを作ります

Effekseerプラグインを導入する

Effekseerのプラグインをプロジェクトに追加します。

プラグインを入手する

こちらからプラグインを入手できます。

github.com

最新バージョンのAssetsのzipをダウンロードします。

中身のaddonsフォルダをプロジェクトにコピーします。
res://addons/effekseer ができるようにします。

これでプラグインのインストールはできました。

プラグインを有効化する

インストールが完了したら、次はGodotで使えるようにします。

プロジェクト設定のプラグインタブからEffekseerを有効化します(有効チェックを入れる)。

これでプラグインの導入は完了です!

エフェクトを探す

https://booth.pm/ja/browse/%E7%B4%A0%E6%9D%90%EF%BC%88%E3%81%9D%E3%81%AE%E4%BB%96%EF%BC%89?q=Effekseer

かっこいいエフェクトが沢山ありますね。ぜひ購入して使わせていただきましょう!

ただ気になるのは、エフェクトの素材はBurst系が多いということです。 例えばアクションゲームで、炎の爆発で敵にダメージを与えるような魔法を作りたいとします。 自分から発射した炎弾が飛んでいき、何かに命中したら爆発するようにしたいです。

炎弾が飛んでいき、敵に命中すると爆発する例

爆発(Burst)はエフェクト素材を使うとして、発射物(Projectile)は自分で何とかしないといけません。 今回はこの発射物エフェクトをEffekseerで作って、Godotで実装するところまで解説したいと思います。

発射物(Projectile)を作る

Effekseerのエディタが無ければダウンロードしておきましょう。 https://effekseer.github.io/jp/

この記事ではこちらの無料のエフェクトを使います。 https://github.com/effekseer/EffectMaterials/

ef_fire01.efkefc

こちらのBurst系エフェクトをProjectile系に改造していきます。

  • 全体的にノードを削減する
    • シンプルにします。沢山撃てるように負荷削減の効果もあります。
  • 炎パーティクルが無限に放出されるようにする
    • 停止命令を受けるまで、エフェクトが勝手に終了しなくなります。
  • 炎パーティクルの「位置への影響」を「生成時のみ」にします
    • 弾の炎が生成位置に残されるようになります
  • 上下方向の移動を少し弱める
    • 好みによります。なるべく弾の軌跡を残したいので。
  • いろいろ微調整
ef_fire01_projectile.efkefc (停止状態)
ef_fire01_projectile.efkefc (飛行状態)

※振る舞いパネルの「移動速度」を設定すると、ルートの移動をシミュレートできます。

Godotに実装する

エフェクトのインポート

Godotに作成したエフェクトをインポートします。
EffekseerEmitter3Dで試しに再生してみます。再生ボタンを押すとエディタビュー上で再生できます。

位置を動かすと炎が残される

炎弾の実装

次に炎弾のシーン(fireball.tscn)を作ってみましょう。

  • CharacterBody3Dをルートにしてシーンを作成します。
  • CollisionShape3Dを追加してShapeにSphereShape3Dを設定します。
  • EffekseerEmitter3Dを追加してEffectにef_fire01_projectile.efkefcを設定します。
  • 今回解説しませんが、爆発時のヒットエリア用にArea3Dを追加しています。

炎弾を制御するスクリプトはこちら。

extends CharacterBody3D

const damage_point = 50  # ヒット時の爆発ダメージ
const speed = 10.0  # 飛行スピード
const lifetime = 3.0  # 飛行限度時間

@onready var _lifecount = 0.0
@onready var _emitter: EffekseerEmitter3D  = $Effect
@onready var _burst_area = $BurstArea    # 爆発の範囲
@onready var _burst_effect = load("res://effects/ef_fire01.efkefc")  # 爆発エフェクト

func _ready():
    # 終了したらfireballシーンを破棄
    _emitter.finished.connect(queue_free)

func _physics_process(delta: float) -> void:
    # 一定時間飛行したら終了する
    _lifecount += delta
    if _lifecount >= lifetime:
        stop()
        return

    # 一定のスピードで前進する
    velocity = transform.basis.z * speed * delta
    var collision = move_and_collide(velocity)
    if collision:  # 何かにぶつかったら爆発する
        burst()

func stop():
    set_physics_process(false)  # 物理更新も停止する
    _emitter.stop_root()  # ルートを停止してなめらかに消えるようにする

func burst():
    # 炎弾エフェクトは停止して、爆発エフェクトを再生
    stop()
    _emitter.effect = _burst_effect
    _emitter.play()

    # おまけ:エネミーにダメージを与える処理
    # for body in _burst_area.get_overlapping_bodies():
    #   if body is EnemyController:
    #       body.damage(damage_point)

炎弾を発射するスクリプトはこちら。

@onready var _fireball := load("res://fireball.tscn")

func spawn_shot():
    var instance = _fireball.instantiate()
    instance.rotation = global_rotation  # 向いている方向を前に設定
    instance.position = global_position + Vector3(0, 0.5, 0)  # 位置を設定。高さ調整
    get_viewport().add_child(instance)  # 

炎弾を発射して、何かに命中すると爆発する魔法ができました!

おわりに

今回はエフェクトの素材を改造してゲームに組み込む方法について解説しました。 エフェクトを1から作るのは結構気合が要るため、少人数でゲームを制作する場合はこういった方法が役に立つかもしれません。