シーン固有ノード
はじめに
get_node() を使用してスクリプトからノードを参照するコードは壊れやすい可能性があります。 たとえばUIシーン内のボタンをあるパネルから別のパネルに移動すると、ボタンのノードパスが変更されます。スクリプトではハードコーディングされたノードパスで get_node() しているため、スクリプトはそのボタンを見つけることができなくなります。
このような状況では、特定のノードをシーン固有ノードに変えることで、そのノードのパスが変更されるたびにスクリプトを更新する必要を回避できます。
シーン固有ノードの作り方
There are two ways to create a scene unique node.
シーンツリードックでノードを右クリックし、コンテキストメニューから 固有名でアクセス を選択します。
固有名でアクセスを選択すると、シーンツリー内のノード名の横にパーセント記号 (%) が表示されます。
You can also do this while renaming the node by adding "%" to the beginning of the name. Once you confirm, the percent symbol will appear next to its name.
これでスクリプト内で固有ノードを使用できるようになります。たとえば get_node() メソッド呼び出しで % 記号を入力し、その後にノード名を入力することで固有ノードを参照できます。
get_node("%RedButton").text = "Hello"
%RedButton.text = "Hello" # Shorter syntax
GetNode<Button>("%RedButton").Text = "Hello";
同一シーンの制限
シーン固有ノードは、同じシーン内のノードによってのみ取得できます。この制限を示すために、Sword シーンをインスタンス化する次の Player シーンの例を考えてみましょう。
Player スクリプト内の get_node() 呼び出しの結果は次のとおり。
get_node("%Eyes")は Eyes ノードを返します。get_node("%Hilt")はnullを返します。
Sword スクリプト内の get_node() 呼び出しの結果は次のとおり:
get_node("%Eyes")はnullを返します。get_node("%Hilt")は Hilt ノードを返します。
スクリプトが別のシーンのノードにアクセスしたいとき、そのノード上で get_node() を呼び出して、そのノードのシーンからシーン固有のノードを取得できます。これはノードパスでもよくて、そうすると複数の get_node() 呼び出しを回避します。シーン固有のノードを使用して Player スクリプトから Hilt ノードを取得する2つの方法を次に示します。
get_node("Hand/Sword").get_node("%Hilt")は Hilt ノードを返します。get_node("Hand/Sword/%Hilt")は Hilt ノードを返します。
シーンの固有名は、ノードパスの末尾でのみ機能するわけではありません。これらはあるノードから別のノードに移動するために中間でも使用できます。たとえば Sword ノードは Player シーン内でシーン固有のノードとしてマークされているため、次のことが可能です。
get_node("%Sword/%Hilt")は Hilt ノードを返します。
代替アプローチ
シーン固有ノードは、シーンをナビゲートするための便利なツールです。ただし状況によっては、他のテクニックの方が優れている場合もあります。
Group を使用すると、2つのノードがどのようなシーンに配置されているかに関係なく、他のノードから特定のノード (または多数のノードのグループ) を見つけることができます。
Singleton (Autoload) はシーンに関係なく任意のノードから直接アクセスできる、常にロードされるノードです。これは一部のデータまたは関数がグローバルに共有される場合に便利です。
Node.find_child() はフルパスを知らなくても名前でノードを検索します。これはシーン固有のノードに似ているように見えますが、この方法はネストされたシーン内の深い所のノードも見つけることができ、シーンエディタでノードをマークする必要はまったくありません。ただしこの方法は時間がかかります。シーン固有のノードはGodotによってキャッシュされ高速に取得できますが、 find_child() はメソッドが呼び出されるたびにすべての子孫 (すべての子、孫など) をチェックする必要があります。