<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>3D on Godot 4 レシピ</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/index.html</link><description>Recent content in 3D on Godot 4 レシピ</description><generator>Hugo -- gohugo.io</generator><language>ja</language><lastBuildDate>Wed, 09 Dec 2020 20:23:50 -0700</lastBuildDate><atom:link href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/index.xml" rel="self" type="application/rss+xml"/><item><title>3Dアセットの扱い方</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/assets/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/assets/index.html</guid><description>&lt;h1 id="3dアセットを扱う"&gt;&lt;i class='fas fa-cubes'&gt;&lt;/i&gt; 3Dアセットを扱う&lt;/h1&gt;
&lt;p&gt;モデル、アニメーション、マテリアルを含むインポートおよび編集方法を解説。&lt;/p&gt;
&lt;p&gt;以下の3Dアセットを使用します。&lt;a href="https://kaylousberg.itch.io/" target="_blank"&gt;Kay Lousberg&lt;/a&gt;提供のものです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kaylousberg.itch.io/kaykit-adventurers" target="_blank"&gt;冒険者キャラクターパック&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kaylousberg.itch.io/kaykit-dungeon-remastered" target="_blank"&gt;ダンジョンアセットパック&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="目次-"&gt;目次 ：&lt;/h4&gt;
&lt;ul class="children children-li children-sort-weight"&gt;
&lt;li&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/assets/importing_assets/index.html"&gt;アセットのインポート&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/assets/character_animation/index.html"&gt;キャラクターアニメーション&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/assets/character_controller/index.html"&gt;キャラクタコントローラー&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>FPSキャラクター</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/basic_fps/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/basic_fps/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;ファーストパーソン・シューティングゲーム（FPS）用のキャラクターを作成してください。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;まず、&lt;i class="gd-CharacterBody3D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody3D&lt;/code&gt; ノードから始め、次に &lt;i class="gd-CollisionShape3D"&gt;&lt;/i&gt;&lt;code&gt;CollisionShape3D&lt;/code&gt; を追加してください。この場合、最も一般的な選択肢は &lt;i class="gd-CapsuleShape3D"&gt;&lt;/i&gt;&lt;code&gt;CapsuleShape3D&lt;/code&gt; 衝突形状です。ワールドの設定によっては、ここに他の形状も追加できますが、この例では基本に忠実に進めます。&lt;/p&gt;
&lt;p&gt;サイズはすべて初期設定値のままにします（カプセルの高さは2メートルとなります）。地面と底面を揃えるため、高さを&lt;code&gt;1.0&lt;/code&gt;m移動させてください。&lt;/p&gt;
&lt;p&gt;次に、ボディの子要素として &lt;i class="gd-Camera3D"&gt;&lt;/i&gt;&lt;code&gt;Camera3D&lt;/code&gt; を追加し、約 &lt;code&gt;1.6&lt;/code&gt;m 持ち上げてください。&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;スクリプトをbodyにアタッチし、まずプロパティを定義することから始めてください。&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;CharacterBody3D&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; gravity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;ProjectSettings&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_setting&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;physics/3d/default_gravity&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; speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;5&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; jump_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;5&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; mouse_sensitivity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0.002&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;_physics_process()&lt;/code&gt;関数は移動処理を担当する箇所です。注意すべき点として、&lt;code&gt;Input.get_vector()&lt;/code&gt;関数は前進/後退/左右キーの組み合わせに基づいて2次元ベクトルを返します。このベクトルを利用して、ボディの速度における&lt;code&gt;x&lt;/code&gt;および&lt;code&gt;z&lt;/code&gt;成分を設定することになります（&lt;code&gt;y&lt;/code&gt;方向は重力によって自動的に処理されるため）。このベクトルにボディの&lt;code&gt;basis&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;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_physics_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; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;gravity &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&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; input &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_vector&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;left&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;right&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;forward&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;back&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; movement_dir &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;basis &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;input&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x&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; input&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; movement_dir&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; speed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;z &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; movement_dir&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;z &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; speed
&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:#88c0d0"&gt;move_and_slide&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:#88c0d0"&gt;is_on_floor&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;and&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;is_action_just_pressed&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;jump&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; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; jump_speed
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;入力マッピングに「W」「A」「S」「D」（標準設定）またはコントローラーの軸（好みに応じて選択可能）を使用して、適切な入力アクションを必ず追加してください。&lt;/p&gt;
&lt;p&gt;以下の手順で「World」シーンにプレイヤーを追加してください。床に&lt;i class="gd-StaticBody3D"&gt;&lt;/i&gt;&lt;code&gt;StaticBody3D&lt;/code&gt;ノードを、壁用に複数のノードを作成済みとします。&lt;/p&gt;
&lt;p&gt;移動しようとすると、前後・左右に動けるものの、回転はできないことがわかります。次はこの点を処理していきます。&lt;/p&gt;
&lt;h2 id="3d空間におけるマウス操作制御"&gt;3D空間におけるマウス操作制御&lt;/h2&gt;
&lt;p&gt;まず、マウスを動かすのと同じ方向にプレイヤーを左／右に回転させる必要があります。マウス入力は画面座標系で2次元的に表現されるため、マウスの水平方向（&lt;code&gt;x&lt;/code&gt;）の動きを、垂直軸である&lt;code&gt;y&lt;/code&gt;を軸にしたプレイヤー本体の回転に変換する必要があります。先ほど定義した&lt;code&gt;mouse_sensitivity&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;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;font-weight:bold"&gt;is&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;InputEventMouseMotion&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;rotate_y&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;event&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;relative&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; mouse_sensitivity&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="https://kamera25.github.io/godot_recipes/4.x/ja/input/mouse_capture/"&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;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;font-weight:bold"&gt;is&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;InputEventMouseMotion&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;and&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;mouse_mode &lt;span style="color:#81a1c1"&gt;==&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;MOUSE_MODE_CAPTURED&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;rotate_y&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;event&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;relative&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; mouse_sensitivity&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;y&lt;/code&gt;モーションを使ってカメラを傾けます。完全に逆さまになるのは避けたいので、回転値は&lt;code&gt;clamp()&lt;/code&gt;で70度という合理的な範囲に制限します。&lt;/p&gt;</description></item><item><title>カメラジンバル</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/camera_gimbal/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/camera_gimbal/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;i class="gd-Camera3D"&gt;&lt;/i&gt;&lt;code&gt;Camera3D&lt;/code&gt;ノードを1つ取得し、&lt;strong&gt;X軸&lt;/strong&gt;（ギズモ上の赤いリング）を中心にわずかに回転させた後、続いて&lt;strong&gt;Z軸&lt;/strong&gt;（青いリング）を中心に少し回転させます。次に、&lt;strong&gt;X軸&lt;/strong&gt;方向の回転を逆方向に反転させ、「プレビュー」ボタンをクリックしてください。カメラが斜めに傾いた状態になっていることが確認できるはずです。&lt;/p&gt;
&lt;p&gt;この問題を解決するには、カメラを &lt;em&gt;ジンバル&lt;/em&gt; に取り付ける必要があります。これは、移動時も物体の水平を保つよう設計された装置です。2つの&lt;i class="gd-Node3D"&gt;&lt;/i&gt;&lt;code&gt;Node3D&lt;/code&gt;ノードを使用することで、左右方向と上下方向の回転を個別に制御できる簡易ジンバルを作成できます。&lt;/p&gt;
&lt;p&gt;ノードの設定は以下のようにしてください。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&lt;i class="gd-Node3D"&gt;&lt;/i&gt; Node3D: CameraGimbal
&lt;i class="gd-Node3D"&gt;&lt;/i&gt; Node3D: InnerGimbal
&lt;i class="gd-Camera3D"&gt;&lt;/i&gt; Camera3D
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;i class="gd-Camera3D"&gt;&lt;/i&gt;&lt;code&gt;Camera3D&lt;/code&gt; の &lt;strong&gt;Transform/Position&lt;/strong&gt; を &lt;code&gt;(0, 0, 4)&lt;/code&gt; に設定してください。&lt;/p&gt;
&lt;p&gt;以下にジンバルの仕組みを説明します。外側ノードは&lt;strong&gt;Y軸方向のみ&lt;/strong&gt;回転可能で、内側ノードは&lt;strong&gt;X軸方向のみ&lt;/strong&gt;回転できます。手動で試したい場合は、まず「ローカル空間を使用」（メニューバーのロックアイコン隣にあるキューブアイコン - ショートカットキーは「T」）に切り替えることを忘れないでください。必ず外側ノードの &lt;em&gt;緑色リング&lt;/em&gt; のみを、内側ノードの &lt;em&gt;赤色リング&lt;/em&gt; のみを操作してください。カメラノードには一切触れないよう注意してください。&lt;/p&gt;
&lt;p&gt;&lt;video controls src="https://kamera25.github.io/godot_recipes/4.x/img/gimbal_01.webm"&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;実験が完了したら、すべての回転値を&lt;code&gt;0&lt;/code&gt;にリセットしてください。&lt;/p&gt;
&lt;h3 id="キーボード操作"&gt;キーボード操作&lt;/h3&gt;
&lt;p&gt;キーボード操作から始めてください。その後、マウスを使用するオプションも追加してください。必要な操作と割り当てられた入力は以下の通りです。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;アクション名&lt;/th&gt;
&lt;th&gt;キー&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;cam_up&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Wキー&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;cam_down&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sキー&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;cam_right&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dキー&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;cam_left&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Aキー&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;cam_zoom_in&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;マウスホイール上方向回転&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;cam_zoom_out&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;マウスホイール下方向回転&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;以下に初期スクリプトを示します。前述の通り、各 &lt;i class="gd-Node3D"&gt;&lt;/i&gt;&lt;code&gt;Node3D&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;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:#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 style="color:#81a1c1"&gt;/&lt;/span&gt;&lt;span style="color:#b48ead"&gt;2&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;get_input_keyboard&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:#616e87;font-style:italic"&gt;# Rotate outer gimbal around y axis&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; y_rotation &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_axis&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;cam_left&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;cam_right&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;rotate_object_local&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;UP&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; y_rotation &lt;span style="color:#81a1c1"&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;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#616e87;font-style:italic"&gt;# Rotate inner gimbal around local x axis&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; x_rotation &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_axis&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#a3be8c"&gt;&amp;#34;cam_up&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;cam_down&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; x_rotation &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;x_rotation &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; invert_y &lt;span style="color:#81a1c1;font-weight:bold"&gt;else&lt;/span&gt; x_rotation
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; inner&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;rotate_object_local&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;RIGHT&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; x_rotation &lt;span style="color:#81a1c1"&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;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:#88c0d0"&gt;get_input_keyboard&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下の手順でテストシーンを作成してください。&lt;/p&gt;</description></item><item><title>補間カメラ</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/interpolated_camera/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/interpolated_camera/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;対象物を滑らかに追従できる3Dカメラが必要となります（補間機能が必要となります）。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&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;Godotに標準搭載されている&lt;code&gt;InterpolatedCamera&lt;/code&gt;ノードは非推奨となっており、Godot 4.0リリース時に廃止される予定です。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以下のスクリプトをシーン内の&lt;i class="gd-Camera3D"&gt;&lt;/i&gt;&lt;code&gt;Camera3D&lt;/code&gt;ノードにアタッチしてください。3つの&lt;code&gt;export&lt;/code&gt;プロパティにより、以下のように選択できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lerp_speed&lt;/code&gt; - カメラの移動速度。値を小さくすると「動きが鈍い」印象になります&lt;/li&gt;
&lt;li&gt;&lt;code&gt;target&lt;/code&gt; - カメラのターゲットノードを選択します&lt;/li&gt;
&lt;li&gt;&lt;code&gt;offset&lt;/code&gt; - ターゲットに対するカメラの相対位置設定です&lt;/li&gt;
&lt;/ul&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;Camera3D&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; lerp_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;3.0&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; target&lt;span style="color:#eceff4"&gt;:&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 style="color:#d08770"&gt;@export&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; offset &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;ZERO
&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;_physics_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; &lt;span style="color:#81a1c1"&gt;!&lt;/span&gt;target&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;return&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; target_xform &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; target&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;global_transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;translated_local&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;offset&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; global_transform &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; global_transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;interpolate_with&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;target_xform&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; lerp_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;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:#88c0d0"&gt;look_at&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;target&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;global_transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;origin&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; target&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;basis&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y&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;_physics_process()&lt;/code&gt;関数内では、カメラの位置を&lt;code&gt;target&lt;/code&gt;の位置（と、&lt;code&gt;offset&lt;/code&gt;を加算した値）に補間します。&lt;/p&gt;
&lt;h3 id="使用例"&gt;使用例&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lerp_speed&lt;/code&gt;: 3.0&lt;/li&gt;
&lt;li&gt;&lt;code&gt;offset&lt;/code&gt;: (0, 7, 5)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;video width="500" controls src="https://kamera25.github.io/godot_recipes/4.x/img/3d_sphere_car_07.webm"&gt;&lt;/video&gt;&lt;/p&gt;</description></item><item><title>レイキャストを使用した射撃</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/shooting_raycasts/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/shooting_raycasts/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;FPSゲームで射撃機能を実装しますが、個別の発射物を手動で動かすのは非現実的です。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;ゲームの物理演算エンジンは、非常に高速で移動するオブジェクトを処理しようとすると破綻しがちです。解決策としては、射手の位置からレイキャストを行い、最初に衝突する物体を検出する方法が有効です。&lt;/p&gt;
&lt;p&gt;Godotにおけるレイキャスティングには、主に2つの方法があります。&lt;i class="gd-RayCast3D"&gt;&lt;/i&gt;&lt;code&gt;RayCast3D&lt;/code&gt;ノードを使用する方法と、物理エンジンを直接操作して空間内に直線状の レイ を投射する方法です。どちらも同じ目的を達成できますが、それぞれに異なる利点があります。ノードベースのアプローチは、継続的な衝突検出が必要な場合に特に有効です - 例えば、床に触れているかどうかを確認するための下向きのレイを継続的にチェックする場合などに最適です。&lt;/p&gt;
&lt;p&gt;2つ目の方法、つまり物理状態を問い合わせる方法を採用します。これは、「発射」キーを押した瞬間に、何かに当たったかどうかを知りたいからです。&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;このレシピでは、すでに動作するFPSキャラクターコントローラーと移動可能なワールドが用意されていることを前提としています。もし用意されていない場合は、先に&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/basic_fps"&gt;FPSキャラクターの作り方&lt;/a&gt;のチュートリアルを参照してください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ヒットした内容を確認するには、&lt;code&gt;FPSPlayer&lt;/code&gt;シーンに&lt;i class="gd-CanvasLayer"&gt;&lt;/i&gt;&lt;code&gt;CanvasLayer&lt;/code&gt;ノードと&lt;i class="gd-Label"&gt;&lt;/i&gt;&lt;code&gt;Label&lt;/code&gt;ノードを追加してください。&lt;/p&gt;
&lt;p&gt;マウス入力を処理するために既に使用している &lt;code&gt;_input()&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;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;shoot&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;shoot&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;shoot()&lt;/code&gt; メソッドを定義します。この関数が呼び出されるたびに、以下の処理を実行する &lt;code&gt;PhysicsRayQueryParameters3D&lt;/code&gt; オブジェクトを作成します。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;レイの始点（カメラ位置）を定義&lt;/li&gt;
&lt;li&gt;レイの終点（カメラから前方100メートル投影された位置）を定義&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;このパラメータはワールドの &lt;code&gt;direct_space_state&lt;/code&gt; を通じて物理エンジンに渡されます。衝突情報を含むDictonaryが返された場合、そのデータに基づいてラベルを更新し、当たったオブジェクトの種類を表示できるようにします。&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;shoot&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; space &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;get_world_3d&lt;/span&gt;&lt;span style="color:#eceff4"&gt;()&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;direct_space_state
&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; query &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;PhysicsRayQueryParameters3D&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;create&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;$Camera3D&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;global_position&lt;span style="color:#eceff4"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $Camera3D&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;global_position &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt; $Camera3D&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;global_transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;basis&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;z &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; &lt;span style="color:#b48ead"&gt;100&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; collision &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; space&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;intersect_ray&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;query&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; collision&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $CanvasLayer/Label&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;text &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; collision&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;collider&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;name
&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; $CanvasLayer/Label&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;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="関連レシピ"&gt;関連レシピ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/basic_fps"&gt;FPSキャラクターの作り方&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="プロジェクトのダウンロード"&gt;&lt;i class="fas fa-code-branch"&gt;&lt;/i&gt; プロジェクトのダウンロード&lt;/h2&gt;
&lt;p&gt;プロジェクトコードはこちらよりダウンロードできます。 &lt;a href="https://github.com/godotrecipes/3d_shoot_castrays" target="_blank"&gt;https://github.com/godotrecipes/3d_shoot_castrays&lt;/a&gt;&lt;/p&gt;</description></item><item><title>CharacterBody3Dの移動</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/characterbody3d_examples/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/characterbody3d_examples/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;プレイヤー操作可能な3Dキャラクターボディが必要となります。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;このレシピでは、こちらの可愛らしいタンクモデルを使用します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-ef851e635fe2be9ed65275c6d6e988a3" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_kinematic_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-ef851e635fe2be9ed65275c6d6e988a3"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_kinematic_01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このモデルは&lt;a href="https://gtibo.itch.io/mini-tank" target="_blank"&gt;Itch.io&lt;/a&gt;で入手できます。他のお好きなモデルを使用しても構いません。ここでは戦車固有の機能は特に実装しません。&lt;/p&gt;
&lt;p&gt;このアセットの場合、ダウンロードには OBJファイルが含まれており、シーンとしてインポートした方が作業が効率的になります。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-afa20dd48835fd8241018b64079cabe8" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/obj_as_scene.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-afa20dd48835fd8241018b64079cabe8"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/obj_as_scene.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;モデルをシーンに追加することはできますが、以下の追加ノードが必要となります。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-70c6cccb135a26d0d616370b9e19f813" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/mini_tank_nodes.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-70c6cccb135a26d0d616370b9e19f813"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/mini_tank_nodes.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;衝突判定形状については、戦車の履帯と位置・サイズを合わせた &lt;code&gt;BoxShape&lt;/code&gt; を使用します。&lt;code&gt;CamPos&lt;/code&gt; は、後続カメラを配置するための &lt;i class="gd-Marker3D"&gt;&lt;/i&gt;&lt;code&gt;Marker3D&lt;/code&gt; です。戦車の後方かつ上部、やや下向きに配置されます。&lt;/p&gt;
&lt;p&gt;また、個別の &lt;i class="gd-MeshInstance3D"&gt;&lt;/i&gt;&lt;code&gt;MeshInstance&lt;/code&gt; ノードを &lt;strong&gt;Y&lt;/strong&gt; 軸を中心に &lt;code&gt;180&lt;/code&gt; 度回転させました。これは元々 &lt;strong&gt;+Z&lt;/strong&gt; 方向を向いてモデル化されていたためですが、Godot では &lt;strong&gt;-Z&lt;/strong&gt; が前方方向となるため、戦車が逆向きに見えるようにはしたくないからです。&lt;/p&gt;
&lt;p&gt;スクリプトを追加する前に、「プロジェクト設定」を開き、「インプットマップ」タブで以下の入力を追加してください。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left"&gt;入力操作&lt;/th&gt;
&lt;th style="text-align: left"&gt;キー&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;前進&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;W&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;後退&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;S&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;右移動&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;D&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left"&gt;左移動&lt;/td&gt;
&lt;td style="text-align: left"&gt;&lt;strong&gt;A&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;CharacterBody3D&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; speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;4.0&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; turn_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0.8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;speed&lt;/code&gt; は戦車の移動速度（前進/後退）を、&lt;code&gt;rot_speed&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;code&gt;@export&lt;/code&gt; でプロパティを宣言しておけば、インスペクタで簡単に調整できるようになります。&lt;/p&gt;</description></item><item><title>3D空間に浮かぶHPバー</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/healthbars/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/healthbars/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;3Dゲームオブジェクト（敵キャラクター、プレイヤーキャラなど）用に、フローティング表示の「HPバー」をつけたい。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;この解決策として、既存の &lt;i class="gd-TextureProgressBar"&gt;&lt;/i&gt;&lt;code&gt;TextureProgressBar&lt;/code&gt; ノードをベースにした 2D HPバーを再利用します。すでにテクスチャが設定されており、値と色を更新するためのコードも実装済みです。既に同様のシステムをお持ちの場合は、それをそのまま使用していただいて構いません。サンプルではこのシーンを「Healthbar2D」と名付けます。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-a395e04466b311cc3e5b6f897142f5ca" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/healthbar_example.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-a395e04466b311cc3e5b6f897142f5ca"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/healthbar_example.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;必要なアセットがある場合、バーで使用している以下の3つの画像を紹介します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-c00c96af72a3060ca92f2e23da70f12e" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/barHorizontal_green_mid%20200.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-c00c96af72a3060ca92f2e23da70f12e"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/barHorizontal_green_mid%20200.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-fad5ea1f4b7671d960b65f30ea9760ac" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/barHorizontal_yellow_mid%20200.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-fad5ea1f4b7671d960b65f30ea9760ac"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/barHorizontal_yellow_mid%20200.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-c7a1807acb88bb5c4e2f3fc0c8c85506" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/barHorizontal_red_mid%20200.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-c7a1807acb88bb5c4e2f3fc0c8c85506"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/barHorizontal_red_mid%20200.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&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;既存のオブジェクトを再利用すれば、大幅に作業時間を節約できます。HPバーやカメラ、その他一般的なコンポーネントが必要なたびにゼロから作り直す必要はありません。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="プロジェクト設定"&gt;プロジェクト設定&lt;/h3&gt;
&lt;p&gt;例として使用する「モブ」の開始点として、&lt;i class="gd-CharacterBody3D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody3D&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;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_on_input_event&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;_camera&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; event&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; _position&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; _normal&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; _shape_idx&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;font-weight:bold"&gt;is&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;InputEventMouseButton&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;and&lt;/span&gt; event&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;button_index &lt;span style="color:#81a1c1"&gt;==&lt;/span&gt; MOUSE_BUTTON_LEFT &lt;span style="color:#81a1c1;font-weight:bold"&gt;and&lt;/span&gt; event&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;pressed&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; health &lt;span style="color:#81a1c1"&gt;-=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;1&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; health &lt;span style="color:#81a1c1"&gt;&amp;lt;=&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;queue_free&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;a href="#image-2246dd8c4a113d3a6b52909bb24b8afd" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_bars01a.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-2246dd8c4a113d3a6b52909bb24b8afd"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_bars01a.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;単位をクリックするたびに1ダメージが与えられます。合計10ダメージを与えると、そのユニットは破壊されます。この状態を2Dバーを使って視覚的に表現する必要があります。&lt;/p&gt;
&lt;h3 id="2dを3dに変換"&gt;2Dを3Dに変換&lt;/h3&gt;
&lt;p&gt;&lt;i class="gd-Sprite3D"&gt;&lt;/i&gt;&lt;code&gt;Sprite3D&lt;/code&gt;を使用することで、2D画像を3D空間で表示することが可能です。新しいシーンに追加し、「Healthbar3D」という名前を付けます。まず設定とサイズ調整を行いますので、 &lt;em&gt;Texture&lt;/em&gt; プロパティに緑色のバー画像を設定してください。&lt;/p&gt;
&lt;p&gt;&lt;i class="gd-Sprite3D"&gt;&lt;/i&gt;&lt;code&gt;Sprite3D&lt;/code&gt;は通常の3Dオブジェクトと同様に動作します。カメラを移動させると、視点が変わるためです。ただし、HPバーは常にカメラの方を向くようにして、いつでも確認できるようにしたいです。&lt;/p&gt;
&lt;p&gt;インスペクターで、 &lt;em&gt;Flags&lt;/em&gt; セクションの &lt;em&gt;Billboard&lt;/em&gt; を「Enabled(有効)」に設定してください。&lt;/p&gt;
&lt;p&gt;続いてカメラを動かして、テクスチャが常にプレイヤー側を向いているか確認してください。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-3159ff5d9ccca215bb6faf0641aeb8eb" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_bars02.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-3159ff5d9ccca215bb6faf0641aeb8eb"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_bars02.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このシーンのインスタンスを&lt;code&gt;Mob&lt;/code&gt;シーンに追加し、バーをモブの体の上に配置してください。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-5f98316706cb1190af004b6e1a6bb6ef" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_bars04.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-5f98316706cb1190af004b6e1a6bb6ef"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_bars04.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="ビューポートテクスチャ"&gt;ビューポートテクスチャ&lt;/h3&gt;
&lt;p&gt;&lt;i class="gd-Sprite3D"&gt;&lt;/i&gt;&lt;code&gt;Sprite3D&lt;/code&gt; ノードが静的なテクスチャを表示するのではなく、&lt;i class="gd-TextureProgressBar"&gt;&lt;/i&gt;&lt;code&gt;TextureProgressBar&lt;/code&gt; を表示したいです。これは、テクスチャをエクスポートできる &lt;i class="gd-SubViewport"&gt;&lt;/i&gt;&lt;code&gt;SubViewport&lt;/code&gt; ノードを使用することで実現できます。&lt;/p&gt;</description></item><item><title>投射物の発射</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/3d_shooting/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/3d_shooting/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;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/kinematic_body/"&gt;CharacterBody3D：移動操作&lt;/a&gt; で設定した「ミニ戦車」を使用します。&lt;/p&gt;
&lt;h3 id="弾丸の設定"&gt;弾丸の設定&lt;/h3&gt;
&lt;p&gt;まず、インスタンス化可能な「弾丸」オブジェクトを設定します。使用するノードは以下の通りです。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&lt;i class="gd-Area3D"&gt;&lt;/i&gt; Area3D: Bullet
&lt;i class="gd-MeshInstance3D"&gt;&lt;/i&gt; MeshInstance
&lt;i class="gd-CollisionShape3D"&gt;&lt;/i&gt; CollisionShape
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;メッシュには、Godotに標準で備わっているプリミティブ形状を使用するか、以下のようなものを作成できます。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-00c58dda19d8e3b0bc09d09cafe8f5ae" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_shoot_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-00c58dda19d8e3b0bc09d09cafe8f5ae"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_shoot_01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&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;a href="https://www.kenney.nl/assets/blaster-kit" target="_blank"&gt;Kenney&amp;rsquo;s &amp;ldquo;Blaster Kit&amp;rdquo;&lt;/a&gt;から入手できます。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;メッシュを &lt;i class="gd-MeshInstance3D"&gt;&lt;/i&gt;&lt;code&gt;MeshInstance&lt;/code&gt; に追加し、衝突形状もそれに合わせてスケール調整してください。&lt;/p&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;i class="gd-MeshInstance3D"&gt;&lt;/i&gt;&lt;code&gt;MeshInstance&lt;/code&gt; を &lt;code&gt;Area3D&lt;/code&gt; ノードの前方方向（&lt;strong&gt;-Z&lt;/strong&gt; 軸）と揃えてください。そうしないと、弾丸が正しく飛んでいるように見えませんよ！&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;スクリプトを追加し、&lt;i class="gd-Area3D"&gt;&lt;/i&gt;&lt;code&gt;Area3D&lt;/code&gt;の&lt;code&gt;body_entered&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;Area3D&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; exploded
&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; muzzle_velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;25&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; g &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;DOWN &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; &lt;span style="color:#b48ead"&gt;20&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; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;ZERO
&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;_physics_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; velocity &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; g &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;look_at&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;origin &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;normalized&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(),&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;UP&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;origin &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; velocity &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&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;_on_Shell_body_entered&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;body&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;exploded&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;origin&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;queue_free&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;g&lt;/code&gt; を使用することで、戦車の砲弾が綺麗な弧を描くように、大砲からどのように飛ぶかを制御できます。もし、飛び道具を直線的に移動させたい場合は、&lt;code&gt;_physics_process()&lt;/code&gt; で重力を適用している行を削除してください。&lt;/p&gt;</description></item><item><title>転がるキューブ</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/rolling_cube/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/rolling_cube/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;3Dで回転するキューブを作成したい。&lt;/p&gt;
&lt;p&gt;&lt;video width="500" controls src="https://kamera25.github.io/godot_recipes/4.x/img/rolling_cube.webm"&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;キューブを転がすのは見た目より難しいです。単に中心軸を中心に回すだけではうまくいきません：&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-ecf316a1a8eccf8c9c0085c73bd795c8" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/cube_001.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-ecf316a1a8eccf8c9c0085c73bd795c8"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/cube_001.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;代わりに、キューブを底面のエッジを中心に回転させます。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-668cde1ea3ec78988a1a153e9e383176" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/cube_002.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-668cde1ea3ec78988a1a153e9e383176"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/cube_002.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ここが重要なポイントです。どの底面の縁でしょうか？ それは、キューブがどの方向に転がっているかによって異なります。&lt;/p&gt;
&lt;p&gt;このレシピを作成するにあたり、異なる解決策を試しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;純粋数学 - 回転変換の計算と適用&lt;/li&gt;
&lt;li&gt;AnimationPlayer - アニメーションを用いた回転およびオフセット制御&lt;/li&gt;
&lt;li&gt;ヘルパーノード - RotationHelperとしてNode3Dを利用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;すべて正常に動作しましたが、最後のオプションが最も柔軟で設定しやすいと感じたので、ここではその方法を採用します。&lt;/p&gt;
&lt;h3 id="ノード設定"&gt;ノード設定&lt;/h3&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Cube: &lt;i class="gd-CharacterBody3D"&gt;&lt;/i&gt; CharacterBody3D
Pivot: &lt;i class="gd-Node3D"&gt;&lt;/i&gt; Node3D
Mesh: &lt;i class="gd-MeshInstance3D"&gt;&lt;/i&gt; MeshInstance3D
Collision: &lt;i class="gd-CollisionShape3D"&gt;&lt;/i&gt; CollisionShape3D
&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;i class="gd-RigidBody3D"&gt;&lt;/i&gt;&lt;code&gt;RigidBody3D&lt;/code&gt;、&lt;i class="gd-CharacterBody3D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody3D&lt;/code&gt;、または &lt;i class="gd-Area3D"&gt;&lt;/i&gt;&lt;code&gt;Area3D&lt;/code&gt;を使用することも可能です。ただし、移動制御の方法には若干の違いが生じます。どのノードを選択するかは、ゲームで他にどのような挙動を必要とするかによって決めるべきです。このレシピでは、単に動きに焦点を当てています。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;デフォルトでは、すべてが座標 &lt;code&gt;(0, 0, 0)&lt;/code&gt; を中心に配置されています。まず最初に行うことは、キューブの&lt;em&gt;底面中央&lt;/em&gt;が &lt;i class="gd-CharacterBody3D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody3D&lt;/code&gt; の位置と一致するように全体をオフセットすることです。&lt;/p&gt;
&lt;p&gt;&lt;i class="gd-BoxMesh3D"&gt;&lt;/i&gt;デフォルトのサイズが &lt;code&gt;(1, 1, 1)&lt;/code&gt; の場合、以下のように設定します。メッシュノードと衝突判定ノードを両方とも &lt;code&gt;(0, 0.5, 0)&lt;/code&gt; に移動し、その他は元のままにします。これでルートノードを選択すると、その位置がキューブの &lt;em&gt;底面&lt;/em&gt; に対応します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-3df5d1a00d83d8ed6b0654705453f8c6" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/cube_003.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-3df5d1a00d83d8ed6b0654705453f8c6"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/cube_003.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;code&gt;0.5&lt;/code&gt;ユニット動かす必要があります。メッシュはオブジェクトに取り付けられているため、反対方向に同じ量だけ動かさなければなりません。例えば、右方向へ転がす場合（&lt;strong&gt;+X&lt;/strong&gt;軸方向）、最終的に以下のコードになります。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-ce0fa4d7528ad26bb2321f3bb4f0e38f" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/cube_004.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-ce0fa4d7528ad26bb2321f3bb4f0e38f"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/cube_004.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;現在、ピボットノードは正しいエッジ上に配置されており、これを回転させるとメッシュ全体が一緒に回転します。&lt;/p&gt;
&lt;h3 id="移動スクリプト"&gt;移動スクリプト&lt;/h3&gt;
&lt;p&gt;この動作は3つのステップに分かれています。&lt;/p&gt;
&lt;h4 id="ステップ1"&gt;ステップ1&lt;/h4&gt;
&lt;p&gt;以下のように、先に示した2つのオフセットを適用します。&lt;code&gt;Pivot&lt;/code&gt;を移動方向にシフトし、&lt;code&gt;Mesh&lt;/code&gt;をその反対方向にシフトします。&lt;/p&gt;</description></item><item><title>移動をカメラに合わせる</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/move_with_camera/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/move_with_camera/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;3D空間でWASD操作を使用している場合、カメラが回転すると方向感覚を失いやすくなります。プレイヤー視点（つまりカメラ）の前進方向と、ゲーム内ワールド内オブジェクトの前方方向、どちらを基準にすべきでしょうか？&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;このケースはさまざまなシナリオに適用できますが、ここでは&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/rolling_cube/"&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;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_physics_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;var&lt;/span&gt; forward &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;FORWARD
&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;if&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&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;up&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;roll&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;forward&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;Input&lt;/span&gt;&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;down&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;roll&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;forward&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;Input&lt;/span&gt;&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;right&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;roll&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;forward&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;cross&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;UP&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;Input&lt;/span&gt;&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;left&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;roll&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;forward&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;cross&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;UP&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;ご覧のとおり、これはグローバル座標系の方向ベクトルを使用しているため、カメラを回転させると「上」がカメラビューで前進しているように見えなくなります。カメラを180度回転させれば、すべてが反転してしまいます！&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; forward &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;camera&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;basis&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;z&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;normalized&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;a href="#image-3ee4d51d49ebaf3c89a3f8f0644496a4" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_move_camera_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-3ee4d51d49ebaf3c89a3f8f0644496a4"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_move_camera_01.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;キューブは4つの基本方向（前後・左右・上下）にのみ移動できます。このため、カメラの前方ベクトルを取得し、どの軸方向に最も近いかを確認する必要があります。&lt;strong&gt;+X&lt;/strong&gt;、&lt;strong&gt;-X&lt;/strong&gt;、&lt;strong&gt;+Z&lt;/strong&gt;、または &lt;strong&gt;-Z&lt;/strong&gt; のいずれかです。&lt;/p&gt;
&lt;p&gt;これは、&lt;code&gt;Vector3.max_axis()&lt;/code&gt;関数を使用してみます。この関数は、ベクトルの成分のうち最も大きい値を返します。値は正または負になる可能性があるため、まず&lt;code&gt;abs()&lt;/code&gt;を適用して絶対値に変換します。&lt;/p&gt;
&lt;p&gt;一旦最大の大きさの軸が特定されれば、以下のように &lt;code&gt;forward&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;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_physics_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;var&lt;/span&gt; forward &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;FORWARD
&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; camera&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; forward &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;ZERO
&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; cam_forward &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;camera&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;basis&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;z&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;normalized&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; cam_axis &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; cam_forward&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;abs&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;max_axis&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; forward&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;cam_axis&lt;span style="color:#eceff4"&gt;]&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;sign&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;cam_forward&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;cam_axis&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;if&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&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;up&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;roll&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;forward&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;Input&lt;/span&gt;&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;down&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;roll&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;forward&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;Input&lt;/span&gt;&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;right&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;roll&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;forward&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;cross&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;UP&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;Input&lt;/span&gt;&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;left&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;roll&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;forward&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;cross&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;UP&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;このクリップでは、移動するために「w」キーのみを押しています。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-29501c76a7f5d26d43cfc35f381fac2b" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_move_camera_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-29501c76a7f5d26d43cfc35f381fac2b"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_move_camera_02.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/3d/spaceship/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/spaceship/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;アーケード／映画のようなスタイルで飛行する3D宇宙船を作りたい。リアルな物理演算は求めず、ドッグファイト主体の『スター・ウォーズ』風の宇宙戦闘スタイルで。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;この機能を実現するため、船のモデルには &lt;i class="gd-CharacterBody3D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody3D&lt;/code&gt; クラスを使用します。ピッチ（前後傾斜）、ロール（横転）、ヨー（回転）の3軸入力により、それぞれ対応する &lt;code&gt;軸&lt;/code&gt; を中心にボディの基底ベクトルが回転します。移動方向は常に前方を指すようになっています。&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;i class="gd-RigidBody3D"&gt;&lt;/i&gt;&lt;code&gt;RigidBody3D&lt;/code&gt;を使用することで実現可能で、同様の結果が得られます。以下にリンクするサンプルプロジェクトでは、リジッドボディ版も含まれていますので、ぜひご参照ください。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="アセット"&gt;アセット&lt;/h3&gt;
&lt;p&gt;宇宙船モデルは以下のアセットパックに含まれています。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://quaternius.com/packs/ultimatespaceships.html" target="_blank"&gt;Quaternius 制作「Ultimate Spaceships Pack」&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;「処刑人」級の艦船モデルを選択しました。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-8160291e1647818d50a0de6b6f3dfe95" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_ship_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-8160291e1647818d50a0de6b6f3dfe95"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_ship_01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ご自由にお好みのデザインをお選びください。&lt;/p&gt;
&lt;h3 id="設定手順"&gt;設定手順&lt;/h3&gt;
&lt;p&gt;操作対象の宇宙船に対応する &lt;code&gt;gltf&lt;/code&gt; ファイルを選択し、&lt;em&gt;インポート&lt;/em&gt;タブをクリックしてください。&lt;em&gt;ルートタイプ&lt;/em&gt;を &lt;i class="gd-CharacterBody3D"&gt;&lt;/i&gt; &lt;code&gt;CharacterBody3D&lt;/code&gt; に変更します。次に『再インポート』をクリックします。その後、&lt;code&gt;gltf&lt;/code&gt;ファイルをダブルクリックすると、新しいシーンが生成され、その中に &lt;i class="gd-KinematicBody3D"&gt;&lt;/i&gt; &lt;code&gt;CharacterBody3D&lt;/code&gt; をルートとする子オブジェクトとして &lt;i class="gd-MeshInstance3D"&gt;&lt;/i&gt; &lt;code&gt;MeshInstance&lt;/code&gt; が表示されます。ボディに &lt;i class="gd-CollisionShape3D"&gt;&lt;/i&gt; &lt;code&gt;CollisionShape3D&lt;/code&gt;を追加してください。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;プロジェクト設定 &amp;gt; インプットマップ&lt;/em&gt; にて、以下の入力を設定してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;roll_right&lt;/code&gt; / &lt;code&gt;roll_left&lt;/code&gt; （ロール操作）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pitch_up&lt;/code&gt; / &lt;code&gt;pitch_down&lt;/code&gt; （ピッチ操作）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;yaw_right&lt;/code&gt; / &lt;code&gt;yaw_left&lt;/code&gt; （ヨー操作）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;throttle_up&lt;/code&gt; / &lt;code&gt;throttle_down&lt;/code&gt; （スロットル操作）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;キーまたはコントローラー入力を割り当てることができます。アナログスティックの入力が最も適しています。&lt;/p&gt;
&lt;h3 id="移動"&gt;移動&lt;/h3&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;CharacterBody&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; max_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;50.0&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; acceleration &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0.6&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; forward_speed &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;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;get_input&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; &lt;span style="color:#8fbcbb"&gt;Input&lt;/span&gt;&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;throttle_up&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; forward_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;lerp&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;forward_speed&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; max_speed&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; acceleration &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;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;Input&lt;/span&gt;&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;throttle_down&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; forward_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;lerp&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;forward_speed&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; acceleration &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;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;_physics_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:#88c0d0"&gt;get_input&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; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;basis&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;z &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; forward_speed
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;move_and_collide&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;velocity &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;i class="gd-Camera3D"&gt;&lt;/i&gt;&lt;code&gt;Camera3D&lt;/code&gt; コンポーネントを試してみます。固定カメラを使用するか、&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/interpolated_camera/"&gt;追従カメラ&lt;/a&gt; を採用することもできます。宇宙船が加速と減速を適切に行うことを確認した上で、次のステップに進んでください。&lt;/p&gt;</description></item><item><title>3Dにおけるベクトル描画</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/debug_overlay/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/debug_overlay/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;3Dゲームで視覚的なデバッグ情報が欲しい。例えば、速度や位置などを表すベクトルを可視化する方法があれば嬉しい。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;2Dでの描画デバッグは非常に便利です。&lt;i class="gd-CanvasItem2D"&gt;&lt;/i&gt;&lt;code&gt;CanvasItem&lt;/code&gt;は&lt;code&gt;_draw()&lt;/code&gt;コールバック内で使用できる多彩なプリミティブ描画メソッドを提供します。3Dの場合、状況はそれほど単純ではありません。一つの解決策として&lt;code&gt;ImmediateGeometry&lt;/code&gt;を使って手動でメッシュを作成する方法がありますが、これは非常に手間がかかり、迅速なデバッグには不便です。&lt;/p&gt;
&lt;p&gt;適切な解決策としては、引き続き&lt;code&gt;CanvasItem&lt;/code&gt;の描画メソッドを使用することです。そのためにはまず、3D空間内の位置を2Dビューポートに投影する必要があります。幸い、&lt;i class="gd-Camera3D"&gt;&lt;/i&gt;&lt;code&gt;Camera&lt;/code&gt;オブジェクトは、その&lt;code&gt;unproject_position()&lt;/code&gt;メソッドを使ってこれを処理してくれます。&lt;/p&gt;
&lt;h3 id="セットアップ方法"&gt;セットアップ方法&lt;/h3&gt;
&lt;p&gt;表示レイヤーについては、3Dシーンに&lt;i class="gd-CanvasLayer"&gt;&lt;/i&gt;&lt;code&gt;CanvasLayer&lt;/code&gt;コンポーネントを追加し、その中に&lt;code&gt;Control&lt;/code&gt;を配置してください。さらに、この&lt;i class="gd-Control"&gt;&lt;/i&gt;&lt;code&gt;Control&lt;/code&gt;にスクリプトを割り当てる必要があります。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-77e83f66401191ebc13e081ba39569a9" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_debug_03.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-77e83f66401191ebc13e081ba39569a9"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_debug_03.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;例：描画制御ノードがプレイヤーノードを参照しており、その&lt;code&gt;velocity(速度)&lt;/code&gt;ベクトルを描画したいとします。また、&lt;i class="gd-Camera3D"&gt;&lt;/i&gt;&lt;code&gt;Camera&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; player
&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; camera
&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;_draw&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; color &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Color&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 style="color:#b48ead"&gt;1&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 style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; start &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; camera&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;unproject_position&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;player&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;global_transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;origin&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; end &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; camera&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;unproject_position&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;player&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;global_transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;origin &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; player&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;velocity&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; node&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;draw_line&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;start&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; end&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; color&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; width&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; node&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;draw_triangle&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;end&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; start&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;direction_to&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;end&lt;span style="color:#eceff4"&gt;),&lt;/span&gt; width&lt;span style="color:#81a1c1"&gt;*&lt;/span&gt;&lt;span style="color:#b48ead"&gt;2&lt;/span&gt;&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; color&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;draw_triangle&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;pos&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; dir&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; size&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; color&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; a &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; pos &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; dir &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; size
&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; b &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; pos &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; dir&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;rotated&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:#81a1c1"&gt;*&lt;/span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;PI&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;&lt;span style="color:#b48ead"&gt;3&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; size
&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; c &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; pos &lt;span style="color:#81a1c1"&gt;+&lt;/span&gt; dir&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;rotated&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;4&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;*&lt;/span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;PI&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;&lt;span style="color:#b48ead"&gt;3&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; size
&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; points &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;PoolVector2Array&lt;/span&gt;&lt;span style="color:#eceff4"&gt;([&lt;/span&gt;a&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; b&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; c&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;draw_polygon&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;points&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;PoolColorArray&lt;/span&gt;&lt;span style="color:#eceff4"&gt;([&lt;/span&gt;color&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;unproject_position()&lt;/code&gt;を使用します。&lt;code&gt;draw_triangle()&lt;/code&gt;は、見栄えの良い尖った矢印形状を表示するために用意されています。&lt;/p&gt;</description></item><item><title>アーケードスタイルのカーゲーム</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/3d_sphere_car/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/3d_sphere_car/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;p&gt;&lt;video width="500" controls src="https://kamera25.github.io/godot_recipes/4.x/img/3d_sphere_car_01.webm"&gt;&lt;/video&gt;&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;ドライビングゲームを作成する方法は数多くあります。各ゲームに求められるリアリズムのレベルは異なります。軽量なアーケードスタイルのカーモデルを作りたい場合、Godotの&lt;i class="gd-VehicleBody3D"&gt;&lt;/i&gt;&lt;code&gt;VehicleBody3D&lt;/code&gt;ノードが提供するすべての機能（サスペンションシステムや個別にモデリングされた車輪など）は必要ないかもしれません。&lt;/p&gt;
&lt;p&gt;その代わり、駆動物理処理は単一の &lt;i class="gd-RigidBody3D"&gt;&lt;/i&gt;&lt;code&gt;RigidBody3D&lt;/code&gt; 球体で処理します。球体自体は視認できない状態にし、車のメッシュをこの球体の位置に配置することで、あたかも球体が車を動かしているかのような視覚効果を実現します。&lt;/p&gt;
&lt;p&gt;上記のプレビュー映像でご覧いただけるように、完成した結果は驚くほど良好です（実際にプレイするのもとても楽しいです！）。引き続きお読みいただければ、必要なコード量も驚くほど少ないことがお分かりいただけるでしょう。&lt;/p&gt;
&lt;h3 id="入力値"&gt;入力値&lt;/h3&gt;
&lt;p&gt;制御用に、以下の4つの入力を［インプットマップ］に追加してください。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;accelerate(加速)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;brake(ブレーキ)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;steer_left(左折)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;steer_right(右折)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;キーボード入力、ゲームパッド、または両方を使用できます。ただし、操作性を重視するなら、アナログスティックの使用をオススメします。&lt;/p&gt;
&lt;h3 id="ノード設定"&gt;ノード設定&lt;/h3&gt;
&lt;p&gt;この車は主に 2 つのノードで構成されています。物理演算用の &lt;i class="gd-RigidBody3D"&gt;&lt;/i&gt;&lt;code&gt;RigidBody3D&lt;/code&gt; 球体と、車体を表示するための &lt;i class="gd-MeshInstance3D"&gt;&lt;/i&gt;&lt;code&gt;MeshInstance3D&lt;/code&gt; です。以下にシーンレイアウトを示します。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&lt;i class="gd-RigidBody3D"&gt;&lt;/i&gt; RigidBody3D (Car)
&lt;i class="gd-CollisionShape3D"&gt;&lt;/i&gt; CollisionShape3D (Sphere)
&lt;i class="gd-Node3D"&gt;&lt;/i&gt; CarMesh (Imported model)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;以下に、各ノードの動作原理を説明します。「加速」を押すと、&lt;i class="gd-RigidBody3D"&gt;&lt;/i&gt;&lt;code&gt;RigidBody3D&lt;/code&gt; に対してオブジェクト（&lt;i class="gd-MeshInstance3D"&gt;&lt;/i&gt;&lt;code&gt;CarMesh&lt;/code&gt;）が向いている方向に力が加わります。一方、旋回入力を入力すると、&lt;i class="gd-MeshInstance3D"&gt;&lt;/i&gt;&lt;code&gt;CarMesh&lt;/code&gt;が回転します。ボールが転がる際、この動きに伴って車のメッシュも移動します（ここではボール自体の回転は考慮しません）。&lt;/p&gt;
&lt;h4 id="カーメッシュ"&gt;カーメッシュ&lt;/h4&gt;
&lt;p&gt;以下が使用する車種の詳細です。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-a2ddcb453996c9dd39aa8c64ea0cee91" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_sphere_car_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-a2ddcb453996c9dd39aa8c64ea0cee91"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_sphere_car_02.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&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;Kenny氏の『カーキット』でこの車種や他のモデルを入手できます。以下のURLからダウンロードできます。
&lt;a href="https://kenney.nl/assets/car-kit" target="_blank"&gt;https://kenney.nl/assets/car-kit&lt;/a&gt;。すべてのアセットをダウンロードできます。使いたいものだけを選んでいただいて構いません。このキットには複数のフォーマット形式のモデルが含まれていますが、プロジェクトに必要な全てを使用する必要はありません。Godotでの使用にはGLTF形式を推奨します。&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;GLTFモデルを使用する場合、インポート設定で調整する必要はありません。&lt;/p&gt;
&lt;p&gt;以下は「suv」モデルをインポートした際のノードツリーの表示例です。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-ead36f83c97cbacfac85fc8c73f38b5a" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_sphere_car_04a.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-ead36f83c97cbacfac85fc8c73f38b5a"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_sphere_car_04a.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;注：ホイールと車体はそれぞれ別のメッシュです。これにより、ステアリング時に車輪が回転するなど、視覚的な演出を簡単に追加できます。&lt;/p&gt;
&lt;h4 id="ボール"&gt;ボール&lt;/h4&gt;
&lt;p&gt;&lt;i class="gd-CollisionShape3D"&gt;&lt;/i&gt;&lt;code&gt;CollisionShape3D&lt;/code&gt; に球形状を追加してください。ここでは半径を &lt;code&gt;1&lt;/code&gt; に設定していますが、異なる走行挙動を得るには、ボールのサイズを調整して実験してみてください。&lt;/p&gt;
&lt;p&gt;以下の方法でボディの設定を調整できます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Angular Damp: &lt;code&gt;10&lt;/code&gt;&lt;/strong&gt; - このプロパティはドライビングのフィーリングに大きな影響を与えます。値が大きいほど、車はより速く停止します。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gravity Scale: &lt;code&gt;5&lt;/code&gt;&lt;/strong&gt; - Godotのデフォルトの重力（&lt;code&gt;9.8&lt;/code&gt;）は、特にアクション性の高いゲームを目指す場合、少し浮遊感があるように感じられます。この設定は、ジャンプや坂道など、ワールド内の起伏を扱う場合に特に重要になります。必要であれば、&lt;strong&gt;プロジェクト設定&lt;/strong&gt;でグローバルに設定することも可能です。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Physics Material/Bounce: &lt;code&gt;0.1&lt;/code&gt;&lt;/strong&gt; - この値を調整することは非常に楽しいですが、0.5を超える値には注意してください！&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;デモ用にデバッグ用として、衝突形状に球状メッシュも追加しました。必須機能ではありませんが、ボールが転がる様子を視覚的に確認できるとトラブルシューティング時に便利です。&lt;/p&gt;</description></item><item><title>アーケードスタイルの飛行機</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/simple_airplane/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/simple_airplane/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;3D空間で飛行機のコントローラーを作りたいが、完全なフライトシミュレーター機能は不要です。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;このレシピでは、&lt;em&gt;単純な&lt;/em&gt;航空機コントローラーを作成します。ここで言う「単純な」とは、基本機能だけに絞り込むことを意味します。目指しているのは、飛行機の操縦感覚――特別な訓練なしですぐに飛び立て、最小限の操作体系で簡単に飛行を楽しめるような体験です。&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;h3 id="ノード設定"&gt;ノード設定&lt;/h3&gt;
&lt;p&gt;このシーンでは &lt;i class="gd-CharacterBody3D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody3D&lt;/code&gt; を使用します。実際の飛行力学（揚力、抗力など）はシミュレートしないため、この場合 &lt;i class="gd-RigidBody3D"&gt;&lt;/i&gt;&lt;code&gt;RigidBody3D&lt;/code&gt; は必要ありません。&lt;/p&gt;
&lt;p&gt;以下にモデルのセットアップをご説明します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-6773fc507ecf11e0655b22347e5011cd" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/kb_plane_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-6773fc507ecf11e0655b22347e5011cd"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/kb_plane_01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&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;CharacterBody3D&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;# Can&amp;#39;t fly below this speed&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; min_flight_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;12&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;# Maximum airspeed&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; max_flight_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;40&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;# Turn rate&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; turn_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0.75&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;# Climb/dive rate&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; pitch_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;0.5&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;# Wings &amp;#34;autolevel&amp;#34; speed&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; level_speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;3.0&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;# Throttle change speed&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; throttle_delta &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;50&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;# Acceleration/deceleration&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; acceleration &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;6.0&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;# Current speed&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; forward_speed &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;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#616e87;font-style:italic"&gt;# Throttle input speed&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; target_speed &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;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#616e87;font-style:italic"&gt;# Lets us change behavior when grounded&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; grounded &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;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; turn_input &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;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt; pitch_input &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;h3 id="操作方法"&gt;操作方法&lt;/h3&gt;
&lt;p&gt;このデモではゲームコントローラーを使用していますが、お好みでキーボード入力を追加することもできます。&lt;/p&gt;</description></item><item><title>クリックして移動</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/click_to_move/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/click_to_move/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;クリックして指定した位置に3Dオブジェクトを移動させたい。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;まず、世界として平面から始めてください。オブジェクトはこの平面上を移動します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-b6037e071524c87c877fc4aaf4b91b47" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_click_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-b6037e071524c87c877fc4aaf4b91b47"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_click_01.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;このデモで使用するアクターは三角柱メッシュです。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-8d51f5074541120d85f209f2e3468dfa" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_click_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-8d51f5074541120d85f209f2e3468dfa"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_click_02.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;CharacterBody3D&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; speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;5&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; gravity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;&lt;span style="color:#b48ead"&gt;5&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; target &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;ZERO
&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;_physics_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; velocity&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; gravity &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&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; target&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;look_at&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;target&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;UP&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; rotation&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &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;span style="display:flex;"&gt;&lt;span&gt; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;basis&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;z &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; speed
&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; transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;origin&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;distance_to&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;target&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#b48ead"&gt;5&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; target &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;ZERO
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; velocity &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;ZERO
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;move_and_slide&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;i class="fa-fw fas fa-MeshInstance3D"&gt;&lt;/i&gt;&lt;i class="gd-MeshInstance3D"&gt;&lt;/i&gt;&lt;code&gt;MeshInstance3D&lt;/code&gt; を追加しました。このオブジェクトは、クリックされた位置を示すために移動します。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-08ad82f659eba3d65be88715b1f7a881" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_click_03.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-08ad82f659eba3d65be88715b1f7a881"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_click_03.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="マウス3d"&gt;マウス→3D&lt;/h3&gt;
&lt;p&gt;現在、マウスの位置を3D空間にマッピングする手段が必要となります。スクリーンを3D世界の窓と見立てると、マウスは画面ガラス上に固定されています。3D空間で何かを選択するには、カメラ（視点）から出発し、マウスの位置を通って現実世界へと伸びるレイを投影しなければなりません。&lt;/p&gt;
&lt;p&gt;これは手動で&lt;i class="gd-Camera3D"&gt;&lt;/i&gt;&lt;code&gt;Camera3D&lt;/code&gt;の&lt;code&gt;project_ray&lt;/code&gt;メソッドを使用して行うことも可能ですが、以下のように、&lt;i class="gd-CollisionObject3D"&gt;&lt;/i&gt;&lt;code&gt;CollisionObject3D&lt;/code&gt;ノードがこの処理を自動的に行う特性を活用することもできます。必要なのは、&lt;i class="gd-StaticBody3D"&gt;&lt;/i&gt;&lt;code&gt;StaticBody3D&lt;/code&gt;グラウンドの&lt;code&gt;input_event&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;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_on_StaticBody_input_event&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;camera&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; event&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; click_position&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; click_normal&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; shape_idx&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;font-weight:bold"&gt;is&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;InputEventMouseButton&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;and&lt;/span&gt; event&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;pressed&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $Marker&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;origin &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; click_position
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $Player&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;target &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; click_position
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;マーカーとプレイヤーのターゲットの位置をクリックされた位置に設定します。&lt;/p&gt;</description></item><item><title>滑らかな回転</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/rotate_interpolate/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/rotate_interpolate/index.html</guid><description>&lt;h2 id="課題"&gt;課題&lt;/h2&gt;
&lt;p&gt;3Dオブジェクトをスムーズに回転させ、新しい方向に向けさせたい場合。&lt;/p&gt;
&lt;h2 id="解決策"&gt;解決策&lt;/h2&gt;
&lt;p&gt;この問題に初めて直面した時、おそらく&lt;strong&gt;x軸/y軸/z軸&lt;/strong&gt;に対する角度を表す3つの値である「オイラー角」の概念が頭に浮かぶでしょう。Godotではオブジェクトのオイラー角を&lt;code&gt;rotation&lt;/code&gt;プロパティで確認できますが、3D環境で作業する際にこれを直接使用するのは推奨されません。これには理由があります。例えば「ジンバルロック」という問題があり、これは回転のうち1つが90度に達すると、自由度が1つ失われてしまう現象です。&lt;/p&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;a href="https://www.youtube.com/watch?v=zc8b2Jo7mno" target="_blank"&gt;こちらの解説動画&lt;/a&gt;がオススメです&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Godotではオブジェクトの&lt;code&gt;transform&lt;/code&gt;プロパティを利用することで、3Dオイラー角を使用する必要を回避できます。このプロパティはオブジェクトの空間内における位置と向きを同時に表現します。これは数学的なマトリックス構造によって実現されていますが、実際に使用する際にはその背後にある数学的原理を理解する必要はありません。&lt;/p&gt;
&lt;h3 id="look_at"&gt;look_at()&lt;/h3&gt;
&lt;p&gt;以下の例では、ミサイルや矢のような3Dオブジェクトを目標方向に向ける方法を示します。これは&lt;i class="gd-Node3D"&gt;&lt;/i&gt;&lt;code&gt;Node3D&lt;/code&gt;クラスの&lt;code&gt;look_at()&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;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;var&lt;/span&gt; target_position &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; $Target&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;origin
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $Arrow&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;look_at&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;target_position&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;UP&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;$Arrow&lt;/code&gt;）がターゲットの位置を常に向くようになります。ターゲットがどのように移動しても関係ありません。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-4dcf0bc70fca34b0700373f059d070a8" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_rotate_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-4dcf0bc70fca34b0700373f059d070a8"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_rotate_01.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;注：&lt;code&gt;look_at()&lt;/code&gt; 関数は2つのパラメーターを必要とします。ターゲット位置と「上方向ベクトル」です。飛行機が目標地点に向かって機首を向ける様子を想像してみてください。機体の向きには無数の方法が考えられます。これは、航空機がその軸を中心に回転できるためです。この第2パラメーターによって、最終的な機体の向きをどのように定義するかを指定します。&lt;/p&gt;
&lt;h3 id="スムーズな回転制御"&gt;スムーズな回転制御&lt;/h3&gt;
&lt;p&gt;上記のコードは動作しますが、回転を瞬時にターゲット位置にスナップさせます。対象物が非常にゆっくりと動いている場合なら許容できるかもしれませんが、見た目に不自然です。開始姿勢から終了姿勢まで、滑らかに「補間」しながら徐々に回転させる方がより自然に見えるでしょう。&lt;/p&gt;
&lt;p&gt;Godotはこの問題も適切に解決しています。&lt;code&gt;look_at()&lt;/code&gt;の代わりに、&lt;code&gt;Transform&lt;/code&gt;オブジェクトの&lt;code&gt;looking_at()&lt;/code&gt;メソッドを使用できます。このメソッドはノード自体を回転させることなく、ターゲットを見るための変換行列を返すだけです。さらに、&lt;code&gt;interpolate_with()&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; speed &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#b48ead"&gt;5&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;var&lt;/span&gt; target_position &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; $Target&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;origin
&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; new_transform &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; $Arrow&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;looking_at&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;target_position&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; &lt;span style="color:#8fbcbb"&gt;Vector3&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;UP&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; $Arrow&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; $Arrow&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;transform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;interpolate_with&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;new_transform&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; 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-4eb5db308f8af7c80e6a475a674aae1a" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_rotate_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-4eb5db308f8af7c80e6a475a674aae1a"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_rotate_02.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;注：&lt;code&gt;interpolate_with()&lt;/code&gt; は &lt;code&gt;transform&lt;/code&gt; を操作するため、回転と位置の両方に対して補間を行えます。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ&lt;/h2&gt;
&lt;p&gt;これで完了です！この便利な方法を使って3Dオブジェクトを回転させ、角度の計算に煩わされることなく作業を進めてください！&lt;/p&gt;
&lt;h2 id="関連レシピ"&gt;関連レシピ&lt;/h2&gt;</description></item><item><title>CharacterBody3D: 表面に位置合わせ</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/3d_align_surface/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/3d_align_surface/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;このレシピは&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/characterbody3d_examples/"&gt;キャラクターボディ3D：移動制御&lt;/a&gt; レシピで解説されている基本の&lt;i class="gd-CharacterBody3D"&gt;&lt;/i&gt;&lt;code&gt;CharacterBody3D&lt;/code&gt;コントローラーを拡張する内容となっています。まずはそちらを先にお読みください。&lt;/p&gt;
&lt;p&gt;まず、シーンに地形を追加しました。こちらのリンクからダウンロードできます。&lt;a href="https://fertile-soil-productions.itch.io/modular-terrain-pack" target="_blank"&gt;https://fertile-soil-productions.itch.io/modular-terrain-pack&lt;/a&gt;。ローポリモデルですが、お好みの地形を自由に使用・作成していただいて構いません。&lt;/p&gt;
&lt;p&gt;ご覧の通り、移動自体は地形に沿って機能していますが、戦車が斜面に対して向きを変えないため、まるで「浮いて」いるかのように見えます。&lt;/p&gt;
&lt;p&gt;&lt;video controls src="https://kamera25.github.io/godot_recipes/4.x/img/3d_kinematic_04.webm"&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;その代わりに、戦車の履帯が地面と平行になるように車体を傾ける必要があります。勾配が変わっても姿勢を維持しなければなりません。そのためには、どの方向が「上」かを把握しておく必要があるのです。&lt;/p&gt;
&lt;h3 id="表面法線ベクトル"&gt;表面法線ベクトル&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;法線ベクトル&lt;/em&gt;（「ノーマルベクトル」または単に「単位ベクトル」）とは、面に垂直な方向を示す単位ベクトルのことです。これは表面がどの向きを向いているのかを定義します。メッシュの場合、各面には必ず外側を指す法線ベクトルが割り当てられます。&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-cfffbdba262875ef189bce10792d8404" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_kinematic_05.png" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-cfffbdba262875ef189bce10792d8404"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_kinematic_05.png" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
&lt;a href="#image-1dc1f7106f4ce07d30a44c8fa485990f" class="lightbox-link"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_kinematic_06.gif" alt="alt" style="height: auto; width: auto;" loading="lazy"&gt;
&lt;/a&gt;
&lt;a href="javascript:history.back();" class="lightbox" id="image-1dc1f7106f4ce07d30a44c8fa485990f"&gt;
&lt;img src="https://kamera25.github.io/godot_recipes/4.x/img/3d_kinematic_06.gif" alt="alt" class="lightbox-image" loading="lazy"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Godot では、衝突が発生した際、接触時の法線ベクトルを取得できます。これは衝突する物体の &lt;strong&gt;接触点における&lt;/strong&gt; 法線方向になります。&lt;/p&gt;
&lt;p&gt;表面法線を取得した後、タンクの&lt;strong&gt;Y&lt;/strong&gt;軸をそれに平行に合わせます。ただし、&lt;code&gt;Transform3D.looking_at()&lt;/code&gt; 関数は使用できません。このメソッドでは &lt;strong&gt;-Z&lt;/strong&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;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;align_with_y&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;xform&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; new_y&lt;span style="color:#eceff4"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;basis&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;y &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; new_y
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;basis&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;x &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;xform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;basis&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;z&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;cross&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;new_y&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;basis &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; xform&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;basis&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;orthonormalized&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;return&lt;/span&gt; xform
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;与えられた変換行列と新しい&lt;strong&gt;Y&lt;/strong&gt;方向ベクトルに基づき、この関数は、指定された法線ベクトルに対して&lt;code&gt;basis.y&lt;/code&gt;成分が一致するよう、適切に回転調整された変換行列を返します。&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;クロス積やその他のベクトル数学に慣れていない方のために、Godot公式ドキュメントに&lt;a href="https://docs.godotengine.org/ja/latest/tutorials/math/vector_math.html" target="_blank"&gt;ベクトル数学入門ガイド&lt;/a&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;func&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;_physics_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; velocity &lt;span style="color:#81a1c1"&gt;+=&lt;/span&gt; gravity &lt;span style="color:#81a1c1"&gt;*&lt;/span&gt; delta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#88c0d0"&gt;get_input&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:#88c0d0"&gt;move_and_slide&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;for&lt;/span&gt; i &lt;span style="color:#81a1c1;font-weight:bold"&gt;in&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;get_slide_count&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; c &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;get_slide_collision&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;i&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; global_transform &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#88c0d0"&gt;align_with_y&lt;/span&gt;&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;global_transform&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; c&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;&lt;span style="color:#88c0d0"&gt;get_normal&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;video controls src="https://kamera25.github.io/godot_recipes/4.x/img/3d_kinematic_07.webm"&gt;&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;問題は、タンクの衝突判定形状が地形面のうち複数箇所と干渉している可能性があることです。さらに、&lt;code&gt;move_and_slide()&lt;/code&gt; 関数では1フレーム内で複数箇所で衝突が発生する場合があり、これが画面表示のカクつき（ジャダー）を引き起こしています。この問題を解決するためには、単一の面を選択し、一貫してその面で判定する必要があります。&lt;/p&gt;
&lt;p&gt;タンクに &lt;i class="gd-RayCast3D"&gt;&lt;/i&gt;&lt;code&gt;RayCast3D&lt;/code&gt; 子要素を追加し、 &lt;strong&gt;ターゲット位置&lt;/strong&gt; を &lt;code&gt;(0, -1, 0)&lt;/code&gt; に設定してください。&lt;/p&gt;</description></item><item><title>3Dで自動車を作ろう</title><link>https://kamera25.github.io/godot_recipes/4.x/ja/3d/kinematic_car/index.html</link><pubDate>Wed, 09 Dec 2020 20:23:50 -0700</pubDate><guid>https://kamera25.github.io/godot_recipes/4.x/ja/3d/kinematic_car/index.html</guid><description>&lt;h1 id="nbsp-3dカーモデル"&gt;&lt;i class="fas fa-car"&gt;&lt;/i&gt; &amp;amp;nbsp 3Dカーモデル&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;CharacterBody3D&lt;/code&gt;を使用して3Dカーを作成しています。&lt;/p&gt;
&lt;h4 id="目次-"&gt;目次 ：&lt;/h4&gt;
&lt;ul class="children children-li children-sort-weight"&gt;
&lt;li&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/kinematic_car/car_base/index.html"&gt;3Dで自動車を作ろう：ベースモデル&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/kinematic_car/car_traction/index.html"&gt;3Dで自動車を作ろう：牽引とドリフト&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/kinematic_car/car_camera/index.html"&gt;3Dで自動車を作ろう：カメラで追いかけよう&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kamera25.github.io/godot_recipes/4.x/ja/3d/kinematic_car/car_slopes/index.html"&gt;3Dで自動車を作ろう：傾斜面＆スロープ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>