<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>基本編 on Godot 4 レシピ</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/basics/index.html</link><description>Recent content in 基本編 on Godot 4 レシピ</description><generator>Hugo -- gohugo.io</generator><language>ja</language><atom:link href="https://kamera25.github.io/godot_recipes/4.x/ja/basics/index.xml" rel="self" type="application/rss+xml"/><item><title>ツリー順序を理解しよう</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/basics/tree_ready_order/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/basics/tree_ready_order/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;Godotがシーンツリー内のノードをどのように処理するかを理解しておく必要があります。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;「ツリー順序」はGodotの公式ドキュメントやチュートリアルで頻出する概念ですが、初心者にはその意味が直感的に理解しにくいものです。基本的に、ノードがツリー内で処理される順番は &lt;strong&gt;上から下へ&lt;/strong&gt; で、ルートノードを起点として、各ブランチごとに順番に下層へと降りていくのが原則です。&lt;/p&gt;
&lt;p&gt;シーンツリーの順序管理は、Godot初心者にとって非常に混乱しやすい要素です。この例では、各処理がどのような順番で実行されるかを具体的に解説します。&lt;/p&gt;
&lt;p&gt;以下にサンプルノード設定例をご紹介します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-b6400fe090e573fcab072c19e9f95ae6" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/tree_order_01.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-b6400fe090e573fcab072c19e9f95ae6"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/tree_order_01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;各ノードには以下のスクリプトがアタッチされています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Node&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_init&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Note: a Node doesn&amp;#39;t have a &amp;#34;name&amp;#34; yet here.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;print&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;TestRoot init&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_enter_tree&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;print&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;name &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34; enter tree&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_ready&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;print&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;name &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34; ready&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#616e87;font-style:italic"&gt;# This ensures we only print *once* in process().&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; test &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; test&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;print&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;name &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34; process&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; test &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;結果について議論する前に、まず各コールバック関数が何を表しているのかを整理します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_init()&lt;/code&gt; はオブジェクトが最初に作成された際に呼び出されます。この時点でオブジェクトのインスタンスがコンピュータのメモリ上に確保されます。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;_enter_tree()&lt;/code&gt; はノードが初めてツリーに追加される際に呼び出されます（インスタンス化時や &lt;code&gt;add_child()&lt;/code&gt; を使用した場合など）。&lt;/p&gt;</description></item><item><title>ノードパスを理解しよう</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/basics/getting_nodes/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/basics/getting_nodes/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;「無効なノード参照」、これはGodotヘルプチャンネルで最も頻繁に報告される問題の一つです。ほとんどの場合、以下のようなエラーメッセージとして表示されます。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Invalid get index &amp;lsquo;position&amp;rsquo; (on base: &amp;rsquo;null instance&amp;rsquo;).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;問題の核心は「nullインスタンス」部分にあり、これがGodot初心者にとって最も混乱を招く要因となっています。&lt;/p&gt;
&lt;p&gt;この問題を回避するには、「ノードパス」の仕組みを理解することが重要です。&lt;/p&gt;
&lt;h3 id="ノードパスの理解"&gt;ノードパスの理解&lt;/h3&gt;
&lt;p&gt;シーンツリーはノードで構成されており、これらは親子関係によって接続されています。ノードパスとは、このツリー構造を辿りながらあるノードから別のノードへ移動する際に通る経路のことです。&lt;/p&gt;
&lt;p&gt;例として、シンプルな「プレイヤー」シーンを考えてみます。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-4b96ce5eb3742c16e40a2ad84fbbee99" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/node_paths_01.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-4b96ce5eb3742c16e40a2ad84fbbee99"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/node_paths_01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このシーンのスクリプトは &lt;code&gt;Player&lt;/code&gt; ノードに実装されています。もしスクリプトが &lt;code&gt;AnimatedSprite&lt;/code&gt; ノードに対して &lt;code&gt;play()&lt;/code&gt; メソッドを呼び出す必要がある場合、そのノードへの参照が必要となります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#88c0d0"&gt;get_node&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;AnimatedSprite&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;play&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;get_node()&lt;/code&gt; 関数の引数は、対象ノードへのパスを表す文字列です。ここではスクリプト実行中のノードの子要素を指定します。指定したパスが無効な場合、厄介な &lt;code&gt;null instance&lt;/code&gt; エラーが発生するほか（さらに「ノードが見つかりませんでした」というメッセージも表示されます）。&lt;/p&gt;
&lt;p&gt;ノード参照を &lt;code&gt;get_node()&lt;/code&gt; で取得する状況は非常に頻繁にあるため、GDScript にはそのためのショートカットが用意されています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$AnimatedSprite&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;play&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="box notices cstyle info"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; 情報&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;&lt;code&gt;get_node()&lt;/code&gt; 関数は、対象ノードへの &lt;strong&gt;参照&lt;/strong&gt; を返します。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ではここで、より複雑なシーンツリーを見てみてください。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-d66bf347ceeb2f23d0cc3d9f39492464" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/node_paths_02.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-d66bf347ceeb2f23d0cc3d9f39492464"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/node_paths_02.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;もし &lt;code&gt;Main&lt;/code&gt; スクリプトが &lt;code&gt;ScoreLabel&lt;/code&gt; にアクセスする必要がある場合、以下のパスを使用してアクセスできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#88c0d0"&gt;get_node&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;HUD/ScoreLabel&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;text &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#616e87;font-style:italic"&gt;# or using the shortcut:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$HUD/ScoreLabel&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;text &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="box notices cstyle tip"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-lightbulb"&gt;&lt;/i&gt; ヒント&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;ドル記号(&lt;code&gt;$&lt;/code&gt;)を使用した場合、Godotエディタがパスを自動補完します。またシーンタブでノードを右クリックし、「ノードのパスをコピー」を選択する方法もあります。&lt;/p&gt;</description></item><item><title>ノード間のやりとり（良い方法）</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/basics/node_communication/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/basics/node_communication/index.html</guid><description>&lt;div class="box notices cstyle info"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-info-circle"&gt;&lt;/i&gt; 情報&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;本記事の元ネタとなった&lt;a href="https://discord.gg/zH7NUgz" target="_blank"&gt;Godot Discord&lt;/a&gt;の@TheDurielによる&lt;a href="https://kamera25.github.io/godot_recipes/4.x/img/node_access_theduriel.png"&gt;原型図&lt;/a&gt;に心から感謝します。この資料は保存しておき、必要に応じて参照できる状態にしておくことをオススメします。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;プロジェクトが複雑化してきました。複数のシーン、インスタンス、そして膨大な数のノードが存在しています。以下のようなコードが沢山ありませんか。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#88c0d0"&gt;get_node&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;../../SomeNode/SomeOtherNode&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#88c0d0"&gt;get_parent&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_parent&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_node&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;SomeNode&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#88c0d0"&gt;get_tree&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_root&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_node&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;SomeNode/SomeOtherNode&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このようにノード参照すると、すぐに問題が発生することに気づくでしょう。シーンツリーの何かを変更すると、これらの参照がすべて無効になる可能性があるからです。&lt;/p&gt;
&lt;p&gt;もっと良い方法があります。ノード間やシーン間のやり取りをシンプルにしていきましょう。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;基本的に、ノードはその子ノードを管理するべきです。逆の関係(子ノードが親ノードを管理する)は避ける必要があります。&lt;code&gt;get_parent()&lt;/code&gt;や&lt;code&gt;get_node(&amp;quot;..&amp;quot;)&lt;/code&gt;を使用している場合、すでに問題が発生し始めています。このようなノードパスは &lt;strong&gt;脆弱&lt;/strong&gt; であり、簡単に壊れてしまう性質があります。この構成には主に3つの重大な問題点があります。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;シーンを単独でテストすることはできません。そのシーン単体、あるいは厳密に同一のノード構成を持たないテストシーンで実行した場合、&lt;code&gt;get_node()&lt;/code&gt; メソッドがクラッシュを引き起こします。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;変更は簡単にはできません。ツリーの構造を変更する場合、パスが無効になる可能性があります。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ノードの&lt;code&gt;_ready()&lt;/code&gt;が呼ばれる順番は、子ノード優先、親ノード後回しとなります。つまり、ノードの &lt;code&gt;_ready()&lt;/code&gt; メソッド内で親プロパティにアクセスしようとすると失敗するケースがあります。これは親ノードがまだ準備中(&lt;code&gt;_ready()&lt;/code&gt;が呼ばれていない)状態であるためです。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="box notices cstyle tip"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-lightbulb"&gt;&lt;/i&gt; ヒント&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;ノードがツリー構造にどのように追加され、準備完了状態になるかについては、&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/basics/tree_ready_order/"&gt;ツリー順序を理解する&lt;/a&gt; を参照してください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;一般的に、ノードやシーンはゲーム内の任意の場所でインスタンス化可能であるべきであり、その親オブジェクトがどのようなものになるかについて一切仮定すべきではありません。&lt;/p&gt;
&lt;p&gt;このチュートリアルでは後ほど詳細な例を紹介しますが、現時点でのノード間通信における「基本原則」は以下の通りです。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;「下には呼び出しで」「上にはシグナルで」&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ノードが子要素を呼び出している場合（つまりツリー構造を「下方向に」移動している場合）には、&lt;code&gt;get_node()&lt;/code&gt; メソッドを使用するのが適切です。&lt;/p&gt;
&lt;p&gt;ノードが「ツリー構造の上位」とやり取りする場合、シグナルを使用する方が適切でしょう。&lt;/p&gt;
&lt;p&gt;シーン設定を設計する際にこのルールを念頭に置いておけば、メンテナンス性に優れ、整理されたプロジェクト構築への道筋が自然と見えてきます。また、問題を引き起こす煩雑なノードパスの使用も避けられるでしょう。&lt;/p&gt;
&lt;p&gt;それでは、これらの戦略を具体例とともに見ていきます。&lt;/p&gt;
&lt;h2 id="1-get_node-を使用する方法"&gt;1. &lt;code&gt;get_node()&lt;/code&gt; を使用する方法&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;get_node()&lt;/code&gt; は、指定されたパスを使用してシーンツリーを辿り、指定した名前のノードを検索します。&lt;/p&gt;
&lt;div class="box notices cstyle tip"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-lightbulb"&gt;&lt;/i&gt; ヒント&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;ノードパスについてより詳しく知りたい場合は、&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/basics/getting_nodes/"&gt;ノードパスの理解&lt;/a&gt;を参照してください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 id="get_node-の使用例"&gt;&lt;code&gt;get_node()&lt;/code&gt; の使用例&lt;/h4&gt;
&lt;p&gt;以下の一般的な設定例について考えてみます。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-1ee4e8eb932d1ea4cc16c7795e777c28" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/node_access_01.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-1ee4e8eb932d1ea4cc16c7795e777c28"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/node_access_01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Player&lt;/code&gt; ノード内のスクリプトでは、プレイヤーの移動状況に応じて、&lt;code&gt;AnimatedSprite2D&lt;/code&gt;にどのアニメーションを再生すべきか通知する必要があります。このようなケースでは &lt;code&gt;get_node()&lt;/code&gt; が適しています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;CharacterBody2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; speed &lt;span style="color:#81a1c1"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;get_node&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;AnimatedSprite2D&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;play&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;run&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;else&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;get_node&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;AnimatedSprite2D&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;play&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;idle&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="box notices cstyle tip"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-lightbulb"&gt;&lt;/i&gt; ヒント&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;GDScriptでは、&lt;code&gt;get_node()&lt;/code&gt;の省略形として&lt;code&gt;$&lt;/code&gt;を使用できます。代わりに&lt;code&gt;$AnimatedSprite2D&lt;/code&gt;と記述してください。&lt;/p&gt;</description></item><item><title>理解しよう！'delta'</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/basics/understanding_delta/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/basics/understanding_delta/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;この&lt;code&gt;delta&lt;/code&gt;パラメーター（delta time）は、ゲーム開発において誤解されがちな概念です。本チュートリアルでは、どのように使用されるのか、フレームレートに依存しない移動の重要性、そしてGodotにおける実践的な使用例について解説します。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;問題を具体的に説明するため、画面上を移動する&lt;code&gt;Sprite&lt;/code&gt;ノードを考えてみます。画面幅が &lt;code&gt;600&lt;/code&gt; ピクセルで、スプライトがこのスクリーン全体を横切るのに &lt;code&gt;5&lt;/code&gt; 秒かかる場合、必要な移動速度は以下の計算で求められます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;600 pixels / 5 seconds = 120 pixels/second
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;_process()&lt;/code&gt;関数を使用して各フレームでスプライトを移動させます。ゲームが &lt;code&gt;60&lt;/code&gt; フレーム/秒で動作している場合、フレームごとの移動量は次のように計算できます：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;120 pixels/second * 1/60 second/frame = 2 pixels/frame
&lt;/code&gt;&lt;/pre&gt;
&lt;div class="box notices cstyle tip"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-lightbulb"&gt;&lt;/i&gt; ヒント&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;上記のすべての計算において、単位が統一されていることに注目してください。常に計算式で使用する単位に注意を払います。これにより、ミスを防ぐことができます。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以下に必要なコードを示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Node2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#616e87;font-style:italic"&gt;# Desired movement in pixels/frame&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; movement &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $Sprite&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;position &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; movement
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;このコードを実行すると、スプライトが画面を横切るのに5秒かかることがわかります。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-86f06176af778f00acfa5485b40dfcc5" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/delta_01.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-86f06176af778f00acfa5485b40dfcc5"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/delta_01.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このコードだと、コンピュータが他のタスクでリソースを消費している場合に問題が発生します。これは「ラグ」と呼ばれます。コード自体の問題や他の実行中アプリケーションに起因する可能性があります。この状況では、フレームの長さが増加します。極端な例として、フレームレートが半減した場合を考えてみます。各フレームの処理時間が60分の1秒から30分の1秒になります。&lt;code&gt;2&lt;/code&gt; ピクセル/フレームで移動しているスプライトの場合、画面端に到達するまでにこれまでの2倍の時間がかかることになります。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-919eab0bbea9bcde7e2002a74794d71c" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/delta_02.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-919eab0bbea9bcde7e2002a74794d71c"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/delta_02.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;たとえ微小なフレームレートの変動があったとしても、動きの速さが一定に保たれなければなりません。これが銃弾など高速で移動する物体であれば、速度が落ちるのを避けたいです。この移動動作を &lt;em&gt;フレームレートに依存しない&lt;/em&gt; ようにする必要があります。&lt;/p&gt;</description></item><item><title>データを保存・読み込む</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/basics/file_io/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/basics/file_io/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;ゲームセッション間でローカルデータを保存と読み込みたいです。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;Godotのファイル入出力（IO）システムは &lt;code&gt;FileAccess&lt;/code&gt; オブジェクトを基盤として構築されています。ファイルをオープンするには &lt;code&gt;open()&lt;/code&gt; メソッドを呼び出します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; file &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;FileAccess&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;open&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;user://myfile.name&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; File&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;READ&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="box notices cstyle warning"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-exclamation-triangle"&gt;&lt;/i&gt; 警告&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;ユーザーデータは &lt;code&gt;user://&lt;/code&gt; パスにのみ保存します。エディタから直接実行している場合には &lt;code&gt;res://&lt;/code&gt; も使用できますが、プロジェクトをエクスポートすると、&lt;code&gt;res://&lt;/code&gt; パスは読み取り専用になります。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ファイルパスに続く2番目の引数は「モードフラグ」であり、以下のいずれかを指定できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FileAccess.READ - 読み取り専用でファイルを開く&lt;/li&gt;
&lt;li&gt;FileAccess.WRITE - 書き込み専用でファイルを開く（存在しない場合は新規作成、存在する場合も先頭から再書き込み）&lt;/li&gt;
&lt;li&gt;FileAccess.READ_WRITE - 読み書き両用モードでファイルを開く（既存ファイルは切り捨てない）&lt;/li&gt;
&lt;li&gt;FileAccess.WRITE_READ - 読み書き両用モードでファイルを開く（存在しない場合は新規作成、存在する場合も先頭から再書き込み）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="データの保存方法"&gt;データの保存方法&lt;/h3&gt;
&lt;p&gt;データの保存には、その専用データ型（&lt;code&gt;store_float()&lt;/code&gt;、&lt;code&gt;store_string()&lt;/code&gt;など）を使用する方法と、汎用的な&lt;code&gt;store_var()&lt;/code&gt;メソッドを使用する方法があります。後者はGodotの組み込みのシリアライゼーション機能を利用してデータをエンコードするため、オブジェクトなどの複雑なデータ構造も扱えます（詳細は後述します）。&lt;/p&gt;
&lt;p&gt;まずは簡単な例から始めてください。プレイヤーのハイスコアを保存する場合を考えます。必要に応じて呼び出せる関数を作成できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; save_path &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;user://score.save&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;save_score&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; file &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;FileAccess&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;open&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;save_path&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;FileAccess&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;WRITE&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; file&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;store_var&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;highscore&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;スコアを保存していますが、ゲーム開始時にこのデータを読み込み可能な状態にしておく必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;load_score&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;FileAccess&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;file_exists&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;save_path&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;print&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;file found&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; file &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;FileAccess&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;open&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;save_path&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;FileAccess&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;READ&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; highscore &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; file&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_var&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;else&lt;/span&gt;&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;print&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;file not found&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; highscore &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ファイルを読み込もうとする前に、まずその存在を確認してください。存在しない場合もあるためです。存在しない場合は、デフォルト値を使用できます。&lt;/p&gt;
&lt;p&gt;必要に応じて任意の数の値に対して何度でも &lt;code&gt;store_var()&lt;/code&gt; および &lt;code&gt;get_var()&lt;/code&gt; を使用できます。&lt;/p&gt;</description></item><item><title>Godot 3.x からの移行</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/basics/migrating/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/basics/migrating/index.html</guid><description>&lt;p&gt;これは、4.0への移行時に注意すべき主要な変更点と「落とし穴」をまとめた随時更新リストです。&lt;/p&gt;
&lt;h2 id="新しい名称"&gt;新しい名称&lt;/h2&gt;
&lt;p&gt;Godot 4での最も大きな変化の一つは、ノード名、関数名、プロパティ名などの大量のリネームです。これらの多くは仕様の一貫性や可読性を向上させるために行われています。特に注意すべき主要な変更点をご紹介します。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;2D/3Dノードの命名規則 - Godot 3.x では2Dノードに「2D」サフィックスが付いていた一方、3Dノードには何も付加されていませんでした。この不整合が解消され、現在ではすべてのノードが「2D」または「3D」を明示するようになりました。具体例：&lt;i class="gd-RigidBody2D"&gt;&lt;/i&gt;&lt;code&gt;RigidBody2D&lt;/code&gt; と &lt;i class="gd-RigidBody3D"&gt;&lt;/i&gt;&lt;code&gt;RigidBody3D&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;3Dカテゴリにおいて、&lt;code&gt;Spatial&lt;/code&gt;ノードは名称を&lt;i class="gd-Node3D"&gt;&lt;/i&gt;&lt;code&gt;Node3D&lt;/code&gt;に統一されています&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;最も人気のあるノードの1つである &lt;code&gt;KinematicBody&lt;/code&gt; が、&lt;i class="gd-CharacterBody2D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody2D&lt;/code&gt;/&lt;i class="gd-CharacterBody3D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody3D&lt;/code&gt; に名称変更されました。このノードに関するAPIの変更点については、以下をご覧ください。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;i class="gd-PackedScene"&gt;&lt;/i&gt;&lt;code&gt;PackedScene&lt;/code&gt; の &lt;code&gt;instance()&lt;/code&gt; 関数は &lt;code&gt;instantiate()&lt;/code&gt; に改名されました&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;position&lt;/code&gt;および&lt;code&gt;global_position&lt;/code&gt;プロパティは、3D空間において従来の&lt;code&gt;translation&lt;/code&gt;と&lt;code&gt;global_translation&lt;/code&gt;に取って代わり、2Dとの一貫性が保たれます。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="シグナルと呼び出し可能オブジェクト"&gt;シグナルと呼び出し可能オブジェクト&lt;/h2&gt;
&lt;p&gt;4.0ではシグナルの扱いが大幅に簡素化されています。&lt;code&gt;signal&lt;/code&gt;はネイティブ型として扱われるようになったため、文字列を使用する機会が減り、オートコンプリートやエラーチェック機能が利用可能になりました。これは関数にも適用され、従来のような文字列参照ではなく、直接関数を指定できるようになりました。&lt;/p&gt;
&lt;p&gt;以下に、シグナルの定義、接続、および送出の具体例を示します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Node&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;signal&lt;/span&gt; my_signal
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_ready&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; my_signal&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;connect&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;signal_handler&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_input&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;event&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; event&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_action_pressed&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;ui_select&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; my_signal&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;emit&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;signal_handler&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;print&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;signal received&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="tweens中間アニメーション"&gt;Tweens（中間アニメーション）&lt;/h2&gt;
&lt;p&gt;Godot 3.5 で &lt;code&gt;SceneTreeTween&lt;/code&gt; を使い始めた場合、Godot 4.0 の &lt;i class="gd-Tween"&gt;&lt;/i&gt;&lt;code&gt;Tween&lt;/code&gt; の使用方法は馴染み深いものでしょう。&lt;/p&gt;
&lt;p&gt;&lt;i class="gd-Tween"&gt;&lt;/i&gt;&lt;code&gt;Tween&lt;/code&gt;はもはやノードとしてありません。代わりに、必要な時に都度1回限りのTweenアニメーションオブジェクトを作成する方式に変更されました。一度慣れてしまえば、従来の方法よりもはるかに強力で使いやすいものとなっています。&lt;/p&gt;
&lt;h2 id="animatedsprite2d3d"&gt;AnimatedSprite[2D|3D]&lt;/h2&gt;
&lt;p&gt;3.x系バージョンに慣れているユーザーにとって最も大きな変化は、&lt;code&gt;playing&lt;/code&gt;プロパティが廃止された点です。現在は&lt;i class="gd-AnimationPlayer"&gt;&lt;/i&gt;&lt;code&gt;AnimationPlayer&lt;/code&gt;との整合性が大幅に改善されており、アニメーションを自動再生するには&lt;strong&gt;SpriteFrames&lt;/strong&gt;パネルでオートプレイ機能を有効にするだけで済みます。コード側では&lt;code&gt;play()&lt;/code&gt;メソッドと&lt;code&gt;stop()&lt;/code&gt;メソッドを使用して、再生制御する形式に変更されました。&lt;/p&gt;
&lt;h2 id="キャラクターボディ-2d3d"&gt;キャラクターボディ [2D/3D]&lt;/h2&gt;
&lt;p&gt;このノードにおける最大の変更点は &lt;code&gt;move_and_slide()&lt;/code&gt; 関数の使用方法です。パラメーターは一切不要となり、すべてが組み込みプロパティとして実装されました。ネイティブの &lt;code&gt;velocity&lt;/code&gt;（速度）プロパティも含まれているため、独自に定義する必要はありません。&lt;/p&gt;
&lt;p&gt;これらのノードの詳細な使用例については、&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/2d/platform_character/"&gt;プラットフォームキャラクター&lt;/a&gt;および／または&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/basic_fps/"&gt;基本FPSキャラクタ&lt;/a&gt;を参照してください。&lt;/p&gt;
&lt;h2 id="タイルマップ"&gt;タイルマップ&lt;/h2&gt;
&lt;p&gt;4.0版では &lt;i class="gd-TileMap"&gt;&lt;/i&gt;&lt;code&gt;TileMap&lt;/code&gt; ノードが全面的にリニューアルされました。&lt;i class="gd-TileSet"&gt;&lt;/i&gt;&lt;code&gt;TileSet&lt;/code&gt;の作成方法からタイルの描画・操作方法まで、ほぼすべてが完全に刷新されています。&lt;/p&gt;
&lt;p&gt;「TileMap の使い方」ガイドが間もなく公開されます。&lt;/p&gt;
&lt;h2 id="乱数生成"&gt;乱数生成&lt;/h2&gt;
&lt;p&gt;以下はGDScriptの組み込み乱数生成関数に対する変更点です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;もう &lt;code&gt;randomize()&lt;/code&gt; を呼び出す必要はありません。自動で処理されます。再現性のある「乱数」が必要な場合は、&lt;code&gt;seed()&lt;/code&gt; で事前に設定した値を指定します。&lt;/p&gt;</description></item><item><title>円運動</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/basics/rotation/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/basics/rotation/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;オブジェクトを別のオブジェクトの周りで「周回」（円軌道を描くように移動）させたい。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;これは初心者がよく抱く疑問で、三角関数をあれこれ試した後によく出てきます。答えは実はとてもシンプルです。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-cef064507b16ac09cafeb4a502250cc8" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/circle_motion_01.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-cef064507b16ac09cafeb4a502250cc8"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/circle_motion_01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;軌道周回させるスプライトをメインスプライトの子ノードに配置します（ここでは「ピボット」と呼びます）。オフセット値を適用し、&lt;code&gt;Pivot&lt;/code&gt;で回転させます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Node2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; rotation_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;PI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $Sprite/Pivot&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;rotation &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; rotation_speed &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;
&lt;a href="#image-f2f849e735f791aa574f9474068a8ca2" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/circle_motion_02.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-f2f849e735f791aa574f9474068a8ca2"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/circle_motion_02.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この手法は3D空間でも同じように機能します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Node3D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; rotation_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;PI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_process&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;delta&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $MeshInstance/Pivot&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;rotate_y&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;rotation_speed &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;
&lt;a href="#image-5656088312b6d7d0595162886763505d" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/circle_motion_03.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-5656088312b6d7d0595162886763505d"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/circle_motion_03.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;</description></item><item><title>カスタムリソースを使用</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/basics/custom_resources/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/basics/custom_resources/index.html</guid><description>&lt;div class="box notices cstyle tips"&gt;
&lt;div class="box-label"&gt;ℹ️ 留意事項&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;この記事は Godot 3から Godot 4 へ内容の書き換え中です。
Godot4では存在しない変数、関数が含まれている場合があります。もしその場合はリポジトリの&lt;a href="https://github.com/kamera25/godot_recipes/issues" target="_blank"&gt;Issues&lt;/a&gt;までご報告ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;ゲーム内でデータを処理する方法や、柔軟なデータオブジェクトを作成する方法を探しています。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;Godotの&lt;code&gt;Resource&lt;/code&gt;クラスは、データを格納・操作するための強力なツールです。Godotで扱う最も一般的なオブジェクトの多くは&lt;a href="https://docs.godotengine.org/ja/stable/classes/class_resource.html#class-resource" target="_blank"&gt;Resource&lt;/a&gt;タイプを拡張しています。アニメーション、衝突形状、画像など。リソースは単なるデータ保持だけでなく、そのデータを操作することもできます（Unityの &lt;em&gt;ScriptableObject&lt;/em&gt; に似ています。）。&lt;/p&gt;
&lt;p&gt;Godot に標準で用意されているすべての &lt;code&gt;リソース&lt;/code&gt;タイプに加え、独自のカスタムリソースを作成してゲーム固有のデータを管理することもできます。これはデータの抽象化とカプセル化を実現する利点があり、ゲーム内の他のあらゆるオブジェクトから利用できる汎用的なコンポーネントを作成できます。&lt;/p&gt;
&lt;h3 id="例プレイヤーの移動"&gt;例：プレイヤーの移動&lt;/h3&gt;
&lt;p&gt;この例では、プラットフォーマーゲームにおけるプレイヤーのHP管理を取り上げます。多くのゲームプレイシステムはプレイヤーのHP・状態と連動しています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;プレイヤーが障害物に衝突するとダメージを受ける場合があります&lt;/li&gt;
&lt;li&gt;敵キャラクターがプレイヤーに触れたり攻撃したりすることでダメージを与えられます&lt;/li&gt;
&lt;li&gt;オブジェクトを拾う、または特定の場所に立つことでプレイヤーが回復できます&lt;/li&gt;
&lt;li&gt;ゲーム画面にはHPゲージを表示し、発生する変化を適切に表示する必要があります&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;さらに、他の相互作用も存在する可能性があります。プレイヤーがHPを減らすとゲームのサウンドトラックが変化する、あるいは敵の行動パターンがプレイヤーのステータスに応じて変化する、といった具合です。&lt;/p&gt;
&lt;div class="box notices cstyle note"&gt;
&lt;div class="box-label"&gt;&lt;i class="fa-fw fas fa-exclamation-circle"&gt;&lt;/i&gt; メモ&lt;/div&gt;
&lt;div class="box-content"&gt;
&lt;p&gt;これは意図的に簡略化した例です。実際の運用では、ここで使用している機能よりも多くの機能が必要になる場合や、ゲームのアーキテクチャに合わせてこの例を修正する必要があるでしょう。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;まず最初に、新しいカスタムリソース&lt;code&gt;PlayerHealth&lt;/code&gt;を定義する必要があります。このリソースはHPに関連するプロパティを管理する必要があります。さらに、HPの変化（回復やダメージを受けるなど）を処理するための機能とシグナルを提供します。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Script&lt;/em&gt; タブで、 &lt;em&gt;ファイル &amp;gt;新規スクリプト&lt;/em&gt; を選択します。&lt;code&gt;Resource&lt;/code&gt;を継承するように設定し、ファイル名を &lt;code&gt;PlayerHealth.gd&lt;/code&gt; とします。&lt;/p&gt;
&lt;p&gt;これを部分ごとに分解して考えてください。&lt;/p&gt;
&lt;p&gt;上部には &lt;code&gt;extends&lt;/code&gt; 行とリソースに割り当てる &lt;code&gt;class_name&lt;/code&gt; があります。このページ名はエディター内の様々な場所で表示されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;extends&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Resource&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;class_name&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;PlayerHealth&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;次に、ゲームオブジェクトがプレイヤーのHP変化を監視するために購読できるシグナルがあります。また、HPがゼロに達するなどの追加イベント用のシグナルも実装できます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;signal&lt;/span&gt; health_changed
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用するプロパティです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; max_value&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; current_value &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この関数を使用すると、HPを最大値に初期化できます。ゲームの再起動時や新しいレベルを開始する際に実行するとよいでしょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;reset&lt;/span&gt;&lt;span style="color:#eceff4"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; current_value &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; max_value
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この関数はプレイヤーにダメージが与えられた際に毎回呼び出されるべきです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript" data-lang="gdscript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;take_damage&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;amount&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; current_value &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;max&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;0&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; current_value &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt; amount&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;emit_signal&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;health_changed&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; current_value&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;この関数はプレイヤーの回復が必要な時に随時呼び出されるべきです。&lt;/p&gt;</description></item></channel></rss>