mobile-development について
Godot 4.x のゲームを Android と iOS に公開する開発者向けのモバイル開発スキルです。署名、ライフサイクル、権限、デバイス API、性能設定など、各プラットフォーム固有の事項を扱います。
主な機能
- 01Android と iOS のエクスポートと署名
- 02アプリの一時停止・再開処理
- 03権限の宣言と実行時リクエスト
- 04Java API とデバイス機能の利用
- 05セーフエリアと画面向きへの対応
- 06モバイル向けレンダラーと性能設定
活用シーン
- 01Android のリリース署名と AAB 出力の設定
- 02アプリ一時停止時のゲーム状態保存
- 03ノッチや画面回転に合わせたレイアウト調整
- 04モバイル向けレンダラーとテクスチャ圧縮の選択
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jame581/ godotprompter --skill mobile-developmentインストール後、Claude Code で/mobile-developmentを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/crash-debugging.mdiap-and-ads.mdplugins.md詳細
モバイル開発
Godot 4.x のゲームを Android と iOS にリリースします。一般的なエクスポートに加えて、署名、ライフサイクル、権限、プラグイン、IAP、デバイス機能、モバイルレンダラーとパフォーマンス予算に関するプラットフォーム固有の差分を扱います。
関連スキル: 一般的なエクスポートの流れと CI/CD については export-pipeline、セーフエリアのレイアウトについては responsive-ui、タッチ入力については input-handling、モバイルのパフォーマンスについては godot-optimization、C# におけるモバイル固有の注意点については csharp-godot を参照してください。
1. エクスポートと署名
Android: OpenJDK 17 と Android SDK を用意し、Editor Settings で Java SDK Path と Android SDK Path を設定します(ユーザーごとの設定であり、プロジェクトごとではありません)。リリース用キーストアを生成します:
keytool -v -genkey -keystore mygame.keystore -alias mygame -keyalg RSA -validity 10000
プリセットの項目:Release / Release User / Release Password(現在、キーストアのパスワードとキーのパスワードは一致している必要があります)。Export With Debug のチェックを外してください。新規の Play へのアップロードには AAB が必須です。 CI の環境変数による上書き:GODOT_ANDROID_KEYSTORE_RELEASE_{PATH,USER,PASSWORD}。
iOS: macOS と Xcode が必要です。エクスポートには App Store Team ID と、逆引き DNS 形式のバンドル Identifier が必要です。Godot は .xcodeproj を生成し、Xcode からビルドします。iOS の シミュレーターでは Compatibility レンダラーを使ってテストしてください。Forward+ と Mobile のサポートは、シミュレーターの Metal に依存します。
カスタム Gradle ビルド(Project → Install the Gradle Build template)は、v2 プラグインと IAP に必須です(Godot 4.2 以降)。Godot 4.7 以降、Use Gradle Build エクスポートオプションは実験的機能の表示がなくなりました(GH-119172)。プラグインまたは IAP が必要な場合は、標準の方法として扱ってください。
⚠️ Godot 4.7 で変更: 非推奨だった Google Play の OBB 拡張ファイルのサポート(
apk_expansion/*エクスポートオプション)は、Android エクスポートから削除されました。引き続き APK 拡張ファイルに依存するプロジェクトは、Android App Bundles と Play Asset Delivery に移行するか、以前のロジックを引き継ぐ独立した Godot OBB plugin をインストールしてください。GH-118283 を参照してください。
2. アプリのライフサイクル
実際の Node 通知定数:NOTIFICATION_APPLICATION_PAUSED(2015)、NOTIFICATION_APPLICATION_RESUMED(2014)、NOTIFICATION_APPLICATION_FOCUS_IN/_OUT(2016/2017)、NOTIFICATION_WM_GO_BACK_REQUEST(1007、Android の戻る操作)。モバイルに WM_CLOSE_REQUEST はありません。 PAUSED 時に自動保存してください。iOS では一時停止後、アプリが終了されるまでに処理を完了する猶予は約 5 秒です。
GDScript
func _notification(what: int) -> void:
match what:
NOTIFICATION_APPLICATION_PAUSED:
SaveManager.save_game() # App backgrounded — persist now.
NOTIFICATION_WM_GO_BACK_REQUEST:
_confirm_quit() # Android Back button.
C# の場合
ドキュメントに記載されているのは NotificationWMCloseRequest のみです。以下の PascalCase 名は、同じ命名規則に従っています。
public override void _Notification(int what)
{
switch ((long)what)
{
case NotificationApplicationPaused:
SaveManager.SaveGame(); // App backgrounded — persist now.
break;
case NotificationWMGoBackRequest:
ConfirmQuit(); // Android Back button.
break;
}
}
ピクチャー・イン・ピクチャー(Android、Godot 4.7 以降)
DisplayServer.pip_mode_enter(window_id = 0) はピクチャー・イン・ピクチャーモードに切り替えます。is_in_pip_mode(window_id = 0) は現在の状態を返します。pip_mode_set_aspect_ratio(numerator, denominator, window_id = 0) は PiP ウィンドウのアスペクト比を設定します。pip_mode_set_auto_enter_on_background(auto_enter_on_background, window_id = 0) は、アプリがバックグラウンドに移行したときに PiP に自動で切り替えます。状態遷移は Node 通知として届きます:NOTIFICATION_APPLICATION_PIP_MODE_ENTERED(2019)/NOTIFICATION_APPLICATION_PIP_MODE_EXITED(2020)。いずれも Android 専用です。
func _ready() -> void:
DisplayServer.pip_mode_set_aspect_ratio(16, 9)
DisplayServer.pip_mode_set_auto_enter_on_background(true)
func _notification(what: int) -> void:
match what:
NOTIFICATION_APPLICATION_PIP_MODE_ENTERED:
_set_minimal_hud(true) # PiP window is tiny — hide non-essential UI.
NOTIFICATION_APPLICATION_PIP_MODE_EXITED:
_set_minimal_hud(false)
public override void _Ready()
{
DisplayServer.PipModeSetAspectRatio(16, 9);
DisplayServer.PipModeSetAutoEnterOnBackground(true);
}
public override void _Notification(int what)
{
switch ((long)what)
{
case NotificationApplicationPipModeEntered:
SetMinimalHud(true); // PiP window is tiny — hide non-essential UI.
break;
case NotificationApplicationPipModeExited:
SetMinimalHud(false);
break;
}
}
3. 権限
エクスポートプリセットで各権限を permissions/<name> として宣言し、実行時に OS.request_permission(name) で要求します。結果は MainLoop の on_request_permissions_result(permission, granted) を通じて届きます。権限は要求するだけでなく、プリセットでも有効にする必要があります。
GDScript
func _ready():
if "android.permission.POST_NOTIFICATIONS" not in OS.get_granted_permissions():
OS.request_permission("android.permission.POST_NOTIFICATIONS")
get_tree().on_request_permissions_result.connect(_on_perm_result)
func _on_perm_result(permission: String, granted: bool):
print("%s granted: %s" % [permission, granted])
C# の場合
// Contains() on string[] needs: using System.Linq;
public override void _Ready()
{
if (!OS.GetGrantedPermissions().Contains("android.permission.POST_NOTIFICATIONS"))
OS.RequestPermission("android.permission.POST_NOTIFICATIONS");
GetTree().OnRequestPermissionsResult += OnPermResult;
}
private void OnPermResult(string permission, bool granted)
=> GD.Print($"{permission} granted: {granted}");
4. Android API の呼び出し(JavaClassWrapper)— Godot 4.4+
Godot 4.4 以降。 JavaClassWrapper.wrap("<java.class>")(それ以前から存在しますが、実用的に使えるのは 4.4 以降です)を使うと、プラグインなしで Java/Kotlin クラスを呼び出せます。4.4 で追加された AndroidRuntime シングルトン(Engine.get_singleton("AndroidRuntime"))では、getActivity()、getApplicationContext()、createRunnableFromGodotCallable(callable) を利用できます。
よりシンプルなクロスプラットフォームの方法として、4.4 を必要としない Input.vibrate_handheld(duration_ms, amplitude) があります(VIBRATE 権限が必要です。iOS では iOS 13 以降が必要です)。JavaClassWrapper/AndroidRuntime の全 API、Toast/Intent のレシピ、内部クラスの構文については、Plugins を参照してください。
GDScript
# Godot 4.4+ — requires the VIBRATE permission in the export preset.
func vibrate_ms(duration_ms: int) -> void:
if Engine.has_singleton("AndroidRuntime"):
var runtime := Engine.get_singleton("AndroidRuntime")
var context := runtime.getApplicationContext()
var vibrator := context.getSystemService("vibrator")
if vibrator.hasVibrator():
var Effect = JavaClassWrapper.wrap("android.os.VibrationEffect")
var effect = Effect.createOneShot(duration_ms, Effect.DEFAULT_AMPLITUDE)
vibrator.vibrate(effect)
C# 相当のコード
ここでのドキュメントは GDScript のみです。正確な C# の Variant マーシャリング処理(Java の各戻り値に対する .AsGodotObject())は実機でテストされていないため、実際の 4.4 以降の Android ビルドで確認してください。
// Godot 4.4+ — requires the VIBRATE permission in the export preset.
public void VibrateMs(int durationMs)
{
if (!Engine.HasSingleton("AndroidRuntime")) return;
var runtime = Engine.GetSingleton("AndroidRuntime");
var context = runtime.Call("getApplicationContext").AsGodotObject();
var vibrator = context.Call("getSystemService", "vibrator").AsGodotObject();
if (vibrator.Call("hasVibrator").AsBool())
{
var effect = JavaClassWrapper.Wrap("android.os.VibrationEffect");
var oneShot = effect.Call("createOneShot", durationMs, effect.Get("DEFAULT_AMPLITUDE"));
vibrator.Call("vibrate", oneShot);
}
}
スクリプトから Java インターフェースを実装する(Godot 4.7+)
JavaClassWrapper.create_proxy(object: Object, interfaces: PackedStringArray) -> JavaObject は Godot オブジェクトを使って、指定された Java インターフェースを実装します。オブジェクトのメソッドシグネチャは Java インターフェースのメソッドシグネチャと一致している必要があり、Java からの呼び出しは一致するメソッドに振り分けられます。create_sam_callback(sam_interface: String, callable: Callable) -> JavaObject は、SAM メソッドのパラメーターと戻り値の型に一致する Callable を使って、単一抽象メソッド(SAM)インターフェースを扱います。どちらも Android 以外のすべてのプラットフォームでは null を返します。
class PrintProxy:
func println(content: String) -> void:
print(content)
func _demo() -> void:
var print_proxy := PrintProxy.new()
var printer := JavaClassWrapper.create_proxy(print_proxy, ["android.util.Printer"])
printer.println("Hello Godot World!")
var cb := func(content: String) -> void: print(content)
var callback := JavaClassWrapper.create_sam_callback("android.util.Printer", cb)
callback.println("Hello Godot World!")
ここでのドキュメントは GDScript のみです。CreateProxy は登録名でメソッドを照合するため、C# の実装クラスでは Java インターフェースと完全に一致するメソッド名が必要です。C# では CreateSamCallback を使うことをおすすめします。
var cb = Callable.From((string content) => GD.Print(content));
var callback = JavaClassWrapper.CreateSamCallback("android.util.Printer", cb);
callback.Call("println", "Hello Godot World!");
5. デバイス機能とセーフエリア
DisplayServer.get_display_safe_area() -> Rect2i(Android/iOS)は、ノッチや切り欠きの内側にある使用可能な領域を返します。get_display_cutouts()(Android)は切り欠きの矩形を一覧表示します。モーションセンサーは Input から利用できます(Vector3 を返す get_accelerometer/gravity/gyroscope/magnetometer。Android/iOS のみ)。
GDScript
func _ready():
var safe := DisplayServer.get_display_safe_area() # Rect2i
$UI.position = safe.position
$UI.size = safe.size
C# 相当のコード
public override void _Ready()
{
Rect2I safe = DisplayServer.GetDisplaySafeArea();
var ui = GetNode<Control>("UI");
ui.Position = safe.Position;
ui.Size = safe.Size;
}
ネイティブのファイルダイアログ(DisplayServer.file_dialog_show())は Android でサポートされています。Godot 4.7 以降では、すべてのデバイスでネイティブのファイルピッカーが動作します。FEATURE_NATIVE_DIALOG_FILE のサポートを制限していた Android バージョンのチェックは削除されました(GH-115257)。
Godot 4.7 以降: 画面上のタッチジョイスティックには、自作の
TouchScreenButton構成ではなく、組み込みのVirtualJoystickControl ノードを使ってください。全 API については、input-handling(references/touch.md、「VirtualJoystick (Godot 4.7+)」)を参照してください。
デバイスの向き変更シグナル(Godot 4.7+)
DisplayServer.orientation_changed(orientation: int)(Android/iOS)は、デバイスの向きが変わると発火します。1 は縦向き、2 は横向き、0 は未定義です。
func _ready() -> void:
DisplayServer.orientation_changed.connect(_on_orientation_changed)
func _on_orientation_changed(orientation: int) -> void:
_relayout_hud(orientation == 2) # 1 portrait, 2 landscape, 0 undefined.
public override void _Ready()
{
DisplayServer.Singleton.Connect(DisplayServer.SignalName.OrientationChanged,
Callable.From((long orientation) => RelayoutHud(orientation == 2)));
}
6. モバイルのパフォーマンスとレンダラー
Mobile(または Compatibility)レンダラーを使用してください。iOS シミュレーターでは Compatibility をおすすめします。Android のテクスチャ圧縮には、rendering/textures/vram_compression/import_etc2_astc = true(ETC2/ASTC)を有効にしてください。単一アーキテクチャの APK は小さく保ち、AAB はデバイスごとに自動で分割されます。描画呼び出しやバッチ処理の詳細な調整は godot-optimization を参照してください。
7. モバイルでの C#
C# の Android/iOS エクスポートは Godot 4.2 以降で実験的に利用できます。Android の C# エクスポートには .NET 9 以降が必要です(Godot 4.5 の場合)。iOS エクスポートは macOS からのみ実行でき(エクスポート時に arm64 と x86_64 のシミュレーターアセンブリもビルドされます)、C# は Web にエクスポートできません。 C# を使うモバイルプロジェクトで最もリスクが高い部分なので、エクスポートのパイプラインを早い段階でテストしてください。
詳細: Plugins (Android v2 / iOS) · In-app purchases & ads · Crash debugging
実装チェックリスト
- リリース用キーストア(Android)/プロビジョニング+チーム ID(iOS)を設定済み
- Play へのアップロードには AAB を使用すること。v2 プラグインまたは IAP を使用する場合は Gradle ビルドをインストール済み
-
NOTIFICATION_APPLICATION_PAUSEDに自動保存を接続済み(iOS の約 5 秒の制限を順守) - プリセットで必要な権限を有効にし、実行時にもリクエスト済み
- JavaClassWrapper の使用箇所に Godot 4.4+ が必要である旨を明記。必要に応じて 4.3 用の代替手段を用意
- UI を
get_display_safe_area()内に配置し、ノッチ/カットアウトに対応 - モバイル/互換レンダラーと ETC2/ASTC 圧縮を有効化
- C# プロジェクト:Android 向けのエクスポートに .NET 9+ が必要であることを確認済み
- Play の OBB/APK 拡張ファイルを Play Asset Delivery を使用する App Bundle に移行するか、Godot OBB プラグインをインストール(組み込みサポートは Godot 4.7 で削除)
- PiP(Android):アスペクト比と自動開始を設定し、HUD が PIP_MODE 通知に反応するよう設定(Godot 4.7+)