大画面や折りたたみ式向けに Unity ゲームを最適化する

1. はじめに

この Codelab では、大画面デバイスと折りたたみ式デバイス向けに Unity Android ゲームを最適化する方法を学びます。Lost Crypt サンプル プロジェクトを使用して、アスペクト比のサポートを実装し、全画面の使用率を拡大し、折りたたみ式デバイスの状態に対応します。

前提条件

  • Unity と Android 開発に関する基礎知識。
  • タブレットや折りたたみ式スマートフォンなどの大画面 Android デバイス。

学習内容

  • さまざまなアスペクト比のサポートを実装する方法。
  • ゲームの UI とカメラの設定でアンカーを使用して、画面サイズに合わせて自動調整する方法。
  • Android の Jetpack Window Manager を使用して、デバイスの折りたたみ時の形状を検出し、レイアウトを調整する方法。

必要なもの

  • Unity Hub と Unity エディタ: Unity 2020 LTS または Unity 2022 がインストールされ、Android ビルドがサポートされていること。
  • ハードウェア: タブレットや折りたたみ式スマートフォンなどの大画面 Android デバイス。
  • スキルを使用する場合は、Google Antigravity などのエージェント型開発プラットフォーム。

2. エージェント スキル

必要に応じて、Unity ゲーム プロジェクトを評価するためのエージェント スキルを利用できます。このスキルは、サイズ変更のサポートと、大画面デバイスおよび折りたたみ式デバイスのサポートを追加するのに役立ちます。詳しくは、GitHub をご覧ください。

このスキルを使用するには:

  1. SKILL.md ファイルをエージェント ディレクトリにコピーします。スキルを追加する方法について詳しくは、Google Antigravity のスタートガイドをご覧ください。
  2. Antigravity などのエージェント型 IDE で、大画面、折りたたみ式デバイス、サイズ変更に関する質問をエージェントに送信します。
  3. エージェントに大画面と折りたたみ式デバイスのサポートを追加するよう依頼します。

3. アスペクト比のサポート

ゲームがさまざまな画面サイズで正しく表示されるようにするには、まずさまざまなアスペクト比のサポートを実装します。さまざまな画面に合うように、カメラやキャンバスのアスペクト比を調整することを検討してください。

  1. アプリが全画面表示のサイズ変更可能な設定を利用していることを確認します。
  2. AndroidManifest.xml(Assets/Plugins/Android/AndroidManifest.xml にあります):
    1. android:resizeableActivity="true" を設定します。
    2. android:screenOrientation="fullSensor" を設定します。

次に例を示します。

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.unity3d.player"
    xmlns:tools="http://schemas.android.com/tools">
    <application>
        <activity android:name="com.unity.lostcryptlargescreenexample.LargeScreenPlayableActivity"
                  android:theme="@style/UnityThemeSelector"
                  android:screenOrientation="fullSensor"
                  android:launchMode="singleTask"
                  android:resizeableActivity="true"
                  android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density"
                  android:hardwareAccelerated="false">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
        </activity>
    </application>
</manifest>
  1. Unity の [Build Settings] で Android プラットフォームの構成を確認します。

注: さまざまなアスペクト比をサポートすることは、タブレットや折りたたみ式デバイスでゲームを美しく表示するための第一歩です。

4. 全画面表示の使用率

さまざまなアスペクト比に対応したら、ゲームが画面全体を使用するようにして、ゲームプレイの没入感を高めます。

画面全体を使用するには:

  1. ゲームの UI とカメラの設定でアンカーを使用します。これにより、UI 要素は画面サイズに合わせて位置を自動的に調整できます。
  2. サンプル プロジェクトの Anchoring シーンを開いて、UI キャンバスのアンカー設定を確認します。
  3. アンカー シーンでは、キャンバスがセーフ フレームを認識するように更新され、移動コントロールが画面の隅に固定されます。

メインカメラのアスペクト比を維持するには、カメラの pixelRect を動的に調整します。CameraAspectLock.cs スクリプトは、向きの変更に対応してカメラビューをレターボックス表示する方法を示しています。

[SerializeField]
private float minAspectRatio = 4f / 3f;

[SerializeField]
private float maxAspectRatio = 21f / 9f;

public void MaintainAspectRatio() {
    int viewWidth = Display.main.systemWidth;
    int viewHeight = Display.main.systemHeight;

    // 1. Calculate screen aspect ratio
    float scaleScreen = viewWidth / (float)viewHeight;
    Rect rect = _camera.pixelRect;

    // 2. Scale to the fullest of the lower between width or height
    if (scaleScreen > maxAspectRatio) {
        // use height, lock width to max at aspect scale
        rect.width = viewHeight * maxAspectRatio;
        rect.height = viewHeight;
    } else if (scaleScreen < minAspectRatio) {
        // use width, lock height to min at aspect scale
        rect.width = viewWidth;
        rect.height = viewWidth / minAspectRatio;
    } else {
        // within allowed aspect ratio range, use full screen
        rect.width = viewWidth;
        rect.height = viewHeight;
    }

    // make sure to center the rect within the window
    rect.x = Mathf.Floor((viewWidth - rect.width) * 0.5f);
    rect.y = Mathf.Floor((viewHeight - rect.height) * 0.5f);

    Debug.Log("camera view width = " + rect.width +
        " height = " + rect.height +
        " x = " + rect.x +
        " y = " + rect.y);

    // 3. Commit the new size to the camera so that it takes effect
    _camera.pixelRect = rect;
}

5. 折りたたみ式デバイスのサポート

折りたたみ式デバイスでは、デバイスの折りたたみ状態(HALF_OPENED、FLAT など)と画面サイズに基づいて、ゲームのレイアウトをその場で調整する必要があります。

  1. Android の Jetpack Window Manager を使用して、デバイスの状態を検出します。
  2. サンプル プロジェクトで、HingeAware シーンを開きます。
  3. このシーンには、Android の Jetpack WindowManager イベントを Unity にブリッジし、UnityEvent コールバックを介して折りたたみ状態に応答する ConfigurationManager MonoBehaviour が含まれています。
  4. HingeSensor.cs は com.unity.lostcryptlargescreenexample.HingeAngleSensor Java プラグインを使用してヒンジ角度を読み取ります。

ConfigurationManager の使用

ConfigurationManager.cs はカスタム Android アクティビティと通信し、状態を表す JSON 文字列を解析します。Android Activity からの onConfigurationChanged コールバックと onFoldChanged コールバックをリッスンします。

[System.Serializable]
public class FoldInfo {
	public string orientation;
	public string state;
	public int isSeparating;
	public int boundsLeft;
	public int boundsTop;
	public int boundsRight;
	public int boundsBottom;
}

public void onFoldChanged(string strFoldInfo) {
	FoldInfo info = JsonUtility.FromJson<FoldInfo>(strFoldInfo);

	// Always call the refresh from the main Unity thread
	StartCoroutine(ExecuteOnMainUnityThread(ActionOnFoldChange, info));
}

getFoldableState プロパティを使用して、状態を同期的にクエリすることもできます。

public static string getFoldableState {
	get {
		if (Application.platform == RuntimePlatform.Android) {
			var foldingFeatureObject = foldablePlayerActivity.Call<AndroidJavaObject>("getFoldingFeature");
			if (foldingFeatureObject != null) {
				var state = foldingFeatureObject.Call<AndroidJavaObject>("getState");
				return state.Call<string>("toString");
			}
		}
		return "NONE";
	}
}

6. HingeSensor を利用する

一部の折りたたみ式デバイスには、折りたたみの正確な角度(0 ~ 360 度)を提供する物理的なヒンジセンサーが搭載されています。これを使用して、ゲームプレイのメカニクスを駆動したり、カメラを調整したりできます。

HingeSensor.cs では、ハードウェア センサーを読み取るために Android プラグインが初期化されます。ヒンジが有効になっているかどうかを確認することもできます。

public class HingeSensor : IDisposable {
	AndroidJavaObject plugin;

	public static HingeSensor Start() {
		if (Application.platform == RuntimePlatform.Android) {
			return OnPlayer.Run(p => {
				var context = p.GetStatic<AndroidJavaObject>("currentActivity");
				var plugin = new AndroidJavaClass("com.unity.lostcryptlargescreenexample.HingeAngleSensor")
						.CallStatic<AndroidJavaObject>("getInstance", context);

				if (plugin != null) {
					plugin.Call("setupSensor");
					return new HingeSensor(plugin);
				}
				return null;
			});
		}
		return null;
	}

	public float GetHingeAngle() {
		return (Application.platform == RuntimePlatform.Android && plugin != null) ? plugin.Call<float>("getHingeAngle") : -1.0f;
	}

	public bool IsHingeEnabled() {
		return Application.platform == RuntimePlatform.Android && plugin != null && plugin.Call<int>("isHingeEnabled") > 0;
	}
}

注: アプリケーションが一時停止または破棄されたときに、バッテリーの消耗を防ぐため、HingeSensor インスタンスで Dispose() または StopSensing() を呼び出すようにしてください。

7. AAB ファイルを作成する

Unity エディタで AAB ファイルを作成する手順は次のとおりです。

  1. Unity エディタで、[ファイル] > [ビルド設定] をクリックします。
  2. [Build App Bundle ( Google Play )] を選択します。詳細については、Android ビルド設定のリファレンスをご覧ください。
  3. [Build] をクリックします。
  4. Unity Editor から AAB ファイルをダウンロードします。

内部テスト版のリリースを作成する

Google Play Console で内部テストのリリースを作成してテスターを追加する手順は次のとおりです。

  1. Google Play Console でゲームを選択します。
  2. [テストとリリース] ページ([テスト] > [内部テスト])に移動します。
  3. [アップロード] をクリックして、AAB ファイルを選択します。
  4. [リリース詳細] フィールドに名前を入力します。
  5. [次へ] をクリックして、リリースの詳細を確認します。
  6. [保存して公開] をクリックします。

8. プロジェクトをビルドして実行する

これで、プロジェクトをビルドしてデバイスでテストする準備が整いました。

  1. ゲームが開いていることを確認します。
  2. Google Play Console で、[ファイル] > [ビルド プロファイル](または [ビルド設定])に移動します。
  3. Google Play Console にアップロードする場合は、[Build App Bundle (Google Play)] がオンになっていることを確認します。または、[Build and Run] をクリックして、接続されたデバイスに直接デプロイします。
  4. 折りたたみ式デバイスを確認し、デバイスの折りたたみ姿勢(HALF_OPENED、FLAT など)と画面サイズに基づいて、ゲームのレイアウトをその場で調整する必要があります。

9. 完了

これで、Unity Android ゲームを大画面や折りたたみ式デバイスに対応させるための原則を学習できました。

アンケート

この Codelab に関するフィードバックをお待ちしております。アンケートへのご協力をお願いいたします。