見出し画像

Particles2Dのプロパティ値が他のノード間で共有されて困った話【Godot Engine】

Particles2Dノードのプロパティ値スクリプトで変更すると、他のParticles2Dノードにも共有してしまい非常に困ってしまった。
今回はそんな話です。


この製作中のゲームでは敵を倒したら爆発するようなパーティクルを描画しようと思い、実際に実装はしてみました。
パーティクルは何度も呼び出すことになるため、シーンとして保存インスタンス化して呼び出すことにしました。

敵を倒したらパーティクルが飛び出すはずが…?

1体目の敵を倒すとパーティクルが生成はされて描画されるのですが、なぜか2体目以降を倒しても表示されません
はて、パーティクルのシーンが呼び出せてないのかなと思って、リモートタブから見てみるものの、ノード自体は呼び出されて実行されているという不思議な事態になっていました。

このパーティクルにはスクリプトの方から透明度のプロパティ値を時間によりだんだん見えなくなっていくという処理がされています。
また、パーティクルが完全にノードとして消滅してから敵を倒すと通常どおり表示されるのです。

ここで気づきます。
新しく生成されたパーティクルにも透明化の現在の値が共有され適応されてしまっているのではないかと。

問題はそれを解決する方法がよくわからないことでした。
敵を高速に倒すことができるゲームシステム上、これができないと画面上さみしく問題がありますよね。
以下は修正後のやりたかった動作です。

本当に求めていたもの

パーティクルの独特な仕様

さてこの問題にぶつかったとき、配信でやっておりまして。
休憩中にあるリスナーさんが問題になっていると思われる原因を見つけたかも? と教えてくれたのが以下のサイトでした。

ここで説明されているのは、Particles2Dを使った実験です。
再現用のプロジェクトファイルもあるので実行するとよくわかると思います。

まさに自分が探していたものでした。

対策は簡単に可能

func _ready():
	process_material = process_material.duplicate()

結果的にこの1行のコードでそれは阻止できます。

内容としては同じプロパティを複製して、このノード独自の固有のものとして扱うという動作です。

なんでも固有化すればいいのではないか?

Particles2D はそのノードのプロパティ値を途中で変更しない場合には起こらない問題です。
そのため、どれもこれも固有化してしまうと、メモリをその分つかってしまったり処理が重くなったりと、良いことばかりではなくなる可能性を秘めています。

もちろん開発がしやすい、管理がしやすいといった利点もありますが、これが大規模なゲームともなると処理の遅さがネックになるかもしれません。
結果修正することに…なんてことに。

終わりに

Particles2D 関連のノードはなるべくノードのインスペクタ上での設定で完結するようにしたほうが処理上は良さそうですね。
今回ボクがやりたかったのは、時間による透明化です。
インスペクタでそれを変更できる部分があればよかったのですが、今のところ解決していません。
もし見つけられればこういう少し良くないコーディングをしなくてもよくなるのに…、と考えると共に、こういうことが起きる危険性があるということがわかりました。

Godot Engine はなるべくコードを複雑化させないための工夫がされていますが、処理的にも良くないことは避けさせようとしている、そんな風にも感じ取れました。

実際にこの問題が起きたときの配信がアーカイブで残っています。
もしよろしかったら、配信に遊びにきてくださいね。

この記事が気に入ったらサポートをしてみませんか?