GodotでジョイスティックUIの実装ガイド
Godot Engine バージョン4.3
このチュートリアルでは、Godotを使い、TextureRectノードを活用してカスタムジョイスティックUIを実装する方法を学びます。マルチタッチのサポートや、ゲーム内でのジョイスティックおよびタッチパッドの動作を理解し、直感的なコントロールを提供する仕組みを構築しましょう。
1. プロジェクトの準備
Godot 4.3 を起動し、新しいプロジェクトを作成します。
Scene を作成し、
Control
ノードをルートノードとして設定します。エディターでマウスを使ってタッチをできるように
Project Settings
でEmulate Touch From Mouse
のチェックをチェックします。
2. シーン構成
Control
ノードの子ノードとして以下の構造を追加します:- TextureRect (名前:
base
) ジョイスティックのベース部分に使用します。
- TextureRect (名前:
handle
) ジョイスティックのハンドル部分に使用します。
TextureRect ノードの設定:
base:
- 任意の円形のベース画像を
Texture
に設定します。
Expand Mode
をIgnore Size
設定しやすくします。
Visible
のチェックを外してデフォルトで非表示にします。
Visibility
をお好みの透明に調整します。
handle:
- 任意の小さな円形画像を
Texture
に設定します。
Expand Mode
をIgnore Size
設定しやすくします。
Visible
のチェックを外してデフォルトで非表示にします。
Visibility
をお好みの透明に調整します。
3. スクリプトの追加
Control
ノードに以下のスクリプトをアタッチします:extends Control
# ジョイスティック用のUI要素@onready var base = $base@onready var handle = $handle
# ジョイスティックのスケール(画面の高さに基づく)デフォルトは0.33(画面高さの33%)@export_category("画面の高さに基づく")@export_range(0,1) var joystick_scale:float = 0.33
# ジョイスティックの指のインデックス# マルチタッチをサポートするため、画面上の指のインデックスまたはIDを追跡する必要がありますvar joystick_finger_index = 0
# ジョイスティックUIのサイズ変数(_ready関数で設定)var joystick_starting_size: floatvar joystick_handle_starting_size: float
# タッチパッドの指のインデックス# マルチタッチをサポートするため、画面上の指のインデックスまたはIDを追跡する必要がありますvar touch_pad_finger_index = 0
# タッチパッド上の最後の位置を記録するベクトル# 現在位置と最後の位置の差分がタッチパッドの出力になりますvar touch_pad_last_position: Vector2 = Vector2.ZERO
# 正規化されたジョイスティックの最終出力(この値を読み取るには get_joystick() を使用)var joystick: Vector2 = Vector2.ZERO
# タッチパッドの最終出力(この値を読み取るには get_touchpad_delta() を使用)var touchpad_delta: Vector2 = Vector2.ZERO
# ウィンドウサイズ変数var window_width = 0var window_height = 0
func _ready(): # 画面サイズの取得 window_width = get_viewport().content_scale_size.x window_height = get_viewport().content_scale_size.y # ジョイスティックのベースとハンドルのサイズを画面の高さとスケールに基づいて設定 joystick_starting_size = window_height * joystick_scale joystick_handle_starting_size = joystick_starting_size / 2 # ジョイスティックのUI要素のサイズを設定 base.size = Vector2(joystick_starting_size, joystick_starting_size) handle.size = Vector2(joystick_handle_starting_size, joystick_handle_starting_size)
func _input(event): # 入力がタッチかどうかを確認 if event is InputEventScreenTouch: # タッチ開始時の処理 if event.pressed: # タッチが画面の左側で、ジョイスティックがまだアクティブでない場合を確認 if event.position.x * get_viewport().get_screen_transform().x.x < window_width / 2 and !joystick_finger_index: # ジョイスティックのタッチを開始 base.show() handle.show() base.position = event.position - (base.size / 2) handle.position = event.position - (base.size / 2) + (handle.size / 2) joystick_finger_index = event.index else: # タッチパッドのタッチを開始 touch_pad_last_position = event.position touch_pad_finger_index = event.index else: # タッチ終了時の処理 if event.index == joystick_finger_index: # ジョイスティックタッチ終了時にUIを非表示にしてジョイスティックをリセット base.hide() handle.hide() joystick = Vector2.ZERO joystick_finger_index = null if event.index == touch_pad_finger_index: # タッチパッドのタッチ終了時 touch_pad_finger_index = null # 入力がタッチドラッグかどうかを確認 if event is InputEventScreenDrag: if event.index == joystick_finger_index: # ジョイスティックのドラッグ処理 var handle_pos = event.position var handle_normalized = event.position handle_pos -= handle.size / 2 handle_normalized -= (base.position + base.size / 2) handle_normalized = handle_normalized / (base.size / 2) joystick = handle_normalized / (base.size / 2) handle_normalized = handle_normalized.normalized() handle_normalized = handle_normalized * (base.size / 2) handle_normalized += (base.position + base.size / 2) handle_normalized -= handle.size / 2 # タッチがジョイスティックのベース外に移動した場合、ハンドルの正規化された位置を使用 # これにより、ジョイスティックのハンドルがベースの外に出ないようにする if event.position.distance_to(base.position + base.size / 2) < base.size.x / 2: handle.position = handle_pos else: handle.position = handle_normalized elif event.index == touch_pad_finger_index: # タッチパッドのドラッグ処理 var movement = event.position - touch_pad_last_position touch_pad_last_position = event.position touchpad_delta += movement
# ジョイスティック値のゲッターfunc get_joystick() -> Vector2: return joystick
# タッチパッド値のゲッター# 重要: タッチパッド値を取得する際は必ず get_touchpad_delta 関数を使用# 入力関数と更新関数が同期していない場合があるため、位置の変化を一時的に保存し、# データが失われないようにするfunc get_touchpad_delta() -> Vector2: var touchpad_delta_return = touchpad_delta touchpad_delta = Vector2.ZERO return touchpad_delta_return
4. 機能の確認
シーンを実行し、画面の左半分をタッチしてジョイスティックUIが表示されることを確認します。
スティックを動かすと、
joystick
値が更新されることを確認します(get_joystick()
を使用)。
5. 応用
ゲームキャラクターの移動に
joystick
の値を使用します。タッチパッド機能を追加することで、複数の指によるコントロールを可能にします。
同じものを一人称ゲームに実装してみました。
モバイルのみジョイスティックが表示されるのでモバイルでぜひ触れてみてください!
これで、Godot を使ったTextureRectベースのジョイスティックUIの実装が完了です。柔軟なUI設計と操作性を実現し、ゲームのプレイ体験を向上させましょう!