壊せるオブジェクトからアイテムを出す
2024/08/25
Godot Engine version 4.2.2 stable
作成者:ダイギイン(アクシオン管理人)

はじめに

キャラクターが樽に当たった時に樽からアイテムが出現するようにしてみます。(fig.1)


fig.1 樽に当たったらアイテムが出る


目次


プロジェクトの準備

まず、サンプルシーンを作成します。(fig.2)
用意するものは、”プレイヤー”、”樽”、”アイテム”の3つです。
サンプルシーンはこちらからダウンロードできますので参考にしてください。


fig.2 サンプルシーン
※クリックで拡大


プレイヤーのシーン

プレイヤーはカーソルキーの右を押すと右に移動し、樽に当たると樽にダメージを与えるようにします。

ルートとなるノードの種類は”Area2D”とし、名前を"Player"にします。
その子に"Sprite2D"、"CollisionShape2D"を追加します。
コリジョンの大きさはスプライトの大きさに合わせます。(fig.3)


fig.3 ノードの準備

"Player"ノードのシグナル"body_enterd(body:Node2D)"を自身に繋ぎます。(fig.4)

fig.4 "body_enterd(body:Node2D)"シグナル
下記のスクリプト(script.1)を"Player"ノードにアタッチします
※ player.gd

script.1 Playerノードのスクリプト


アイテムのシーン

アイテムは、実ゲームでは必要なので、とりあえず当たり判定を付けておきます。(fig.5)
コリジョンのレイヤーとマスクはプレイヤーとは別の番号を有効にします。
スクリプトはアタッチしません。


fig.5 アイテムのシーン


樽のシーン

樽は体力(HP)を設定して0以下になったらアイテム出現と"Break"アニメーションを再生し、
アニメーション終了時に自身を削除するようにします。

まず、ノードの構成とコリジョンの設定は次の図のようにします。(fig.6)


fig.6 樽のシーン
※クリックで拡大

次に、Taruノードにアタッチするスクリプトは下記のようになります。(script.2)
※ taru.gd

script.2 Taruノードのスクリプト

"script.2"でキモになるのは、アイテムを出現させる部分です。(fig.7)

fig.7 アイテムを出す部分のスクリプト

順番に解説します。

var temp_node = Item.instantiate()
スクリプトの冒頭で"preload"したアイテムのシーンを実体化します。
実体化したノードは仮のノードに紐づけします。

# add_child()を呼び出し可能状態にする
var callable = owner.add_child.bind(temp_node)
ここでは次の行で親ノードにぶら下げる前に一旦、呼び出し可能な状態としておきます。
"add_child"メソッドの呼び出しをフレームごとに遅延させるために必要です。
忘れがちですが"bind"メソッドを入れるようにします。

# 呼び出し可能にしたadd_child()を1フレーム空けて呼び出す
get_tree().process_frame.connect(callable, CONNECT_ONE_SHOT)
当たり判定の処理中にツリー中のノードの位置が変更されても不都合がないように
先ほどのメソッドを1フレーム遅延させて呼び出します。
引数"CONNECT_ONE_SHOT"ならば1回のみ実行を指示します。


これらの処理を行わなかった場合のスクリプト(fig.8)ではどうなるでしょうか?

fig.8 遅延呼び出しを行わなかった場合のスクリプト

アイテムを出す段階で次のエラーが出ます。(fig.9)

fig.9 エラー表示

これはしっかり調べてはいないので、はっきり言えず申し訳ございません。
このエラーは連続で複数回発せられることもあります。


実行確認

シーンにプレイヤーと樽を配置したら実行してみましょう。(fig.1)


fig.1 樽に当たったらアイテムが出る


おわりに

エラーの解決にあたり、"call_deferred"を調べるところから始めました。
bingの翻訳機能を使いつつなんとか解決できた感じです。
本件と同じエラーは過去にもあり、その時は別の方法に切り替えて対処しましたが、
ようやく雛形が見えた気がします。

今回の記事はここまでとなります。
最後までお読みいただきありがとうございました。


参考文献

Godot Engine 4.3の日本語のドキュメント -> Object -> call_deferred
https://docs.godotengine.org/ja/4.x/classes/class_object.html#class-object-method-call-deferred

ページトップ