"Godot Engine" GDScript 9 「change_scene() でシーン・チェンジ」
「ボタンを押すと、シーンが変わる」という一連の動作が出来るようになったので、書いておこうと思う。「ボタンを押す」 > 「シグナルが出る」 > 「何かする」 という一連の手順は以前やったが、おさらいしながら進む。
シーンとボタンを準備しよう
[1] 新しいプロジェクトを作成して、シーンを2つに。[メニュー] > [Scene] > [New Scene] で空のシーンが2つある状態に。
[2] 各シーンを以下のように作る。(ラベルノードとボタンノードの "Text" プロパティはお好きに) シーンにノードを置いていない状態ではセーブできないので、ノードを置いてから、[Ctrl] + [S] で名前を付ける。
[3] 「シーンAAAA」に置いたボタンにスクリプトを付ける。スクリプトの中身はなにもいじらなくてOK。
信号受信ノードにスクリプトを付けるのが、最初に行う準備だった。今回は、信号を出すのも受けるのも同じボタンノードで行うので、ここにスクリプトを付ける。だがこれは、信号を出すから付けているのではなく、あくまで受信するからである事に注意。
[4] 信号送信の準備をする。ノードパネルに切り替えて、"pressed()" をダブルクリック。当然だが、シーンパネルでボタンノードが選択されている事。
[5] 確認窓が開く。信号受信は、信号発信をするボタンノードに付いているスクリプトなので、ちゃんと選んで、[接続]。
(おっと、"Method In Node" ってわざわざ「メソッド」書いてあるけど、関数って呼ぶ俺。俺はなんでもかんでも関数派。)
[6] [接続]するとスクリプトに、信号受信時に呼ばれる関数を追加してくれる。中身(ボディ)が空なので、pass
というキーワードが入っている。
[7] スクリプトを修正。「シーンAAAA」では、ボタンを押すと「シーンBBBB」に変わるようにしたい。以下のように修正。
コピペ用
func _on_Button_pressed(): get_tree().change_scene("res://BBBB.tscn")
【解説】
get_tree()
: シーンツリー(Godot が用意している「Viewport」がいっこだけのアレ)を操作しますよ、って事。ボタンノードのスクリプトからは、いきなりSceneTree
クラスで定義されているchange_scene()
関数を呼べないので、get_tree()
として、SceneTree
クラスで定義されている関数を使えるようにしている、とも言える。Node
クラスで定義されている。change_scene()
: シーンツリーに入っているノードを全部クリアして(Godot が用意している「Viewport」以外)、( ) 内のシーンにあるノードを追加しますよって事。SceneTree
クラスで定義されている。get_tree()
とchange_scene()
を "." (ドット)で繋ぐので注意。こうやって操作対象を先に指定して、"." を挟んでその後に操作を記述する表記がある。以前やった、get_node()
もこれと同じ使い方をしている。(ドットシンタックス(dot syntax)、とか言うみたい)- "res://BBBB.tscn": ( ) 内で指定するシーンは、" " で挟んだパス名。"res://" は Godot 独自のプロジェクトフォルダを指す表現だった。
- 忘れちゃいけないのが、
get_tree()
の前のインデント。関数のボディを書く時の立派な文法のひとつ。
[8] 同様の手順で「シーンBBBB」の方も「ボタンを押すと何かする」の操作を行う。スクリプトに修正をする部分が、"res://BBBB.tscn" から "res://AAAA.tscn" になるだけ。一応コピペ用
func _on_Button_pressed(): get_tree().change_scene("res://AAAA.tscn")
出来たらシーンを再生してみよう
一応、[メニュー] > [Scene] > [Save all Scenes] で両シーンをセーブして、「シーンAAAA」をタブで指定してから(シーンBBBBでもいいけど)、右上ツールの [シーン再生] ボタンを押してみよう。
うむ。この仕組みをエアホッケーに組み込めばいいだけだ。だが・・・。
たまに、[Copy Path] がうまく働かない時があるんだが、仕様?