대형 화면 및 폴더블 기기에 맞게 Unity 게임 최적화하기

1. 소개

이 Codelab에서는 대형 화면 및 폴더블 기기에 맞게 Unity Android 게임을 최적화하는 방법을 알아봅니다. Lost Crypt 샘플 프로젝트를 사용하여 가로세로 비율 지원을 구현하고, 전체 화면 활용도를 높이고, 폴더블 상태에 응답합니다.

기본 요건

  • Unity 및 Android 개발에 관한 기본적 이해
  • 태블릿이나 폴더블 스마트폰과 같은 대형 화면 Android 기기

학습 내용

  • 다양한 가로세로 비율을 지원하는 방법을 알아봅니다.
  • 게임의 UI 및 카메라 설정에서 앵커를 사용하여 화면 크기에 맞게 자동으로 조정하는 방법
  • Android의 Jetpack Window Manager를 사용하여 기기의 폴딩 자세를 감지하고 레이아웃을 조정하는 방법

필요한 항목

  • Unity Hub 및 편집기: 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 활동에서 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 Editor에서 AAB 파일을 만들려면 다음 단계를 따르세요.

  1. Unity 편집기에서 File > Build settings를 클릭합니다.
  2. Build App Bundle ( Google Play)을 선택합니다.자세한 내용은 Android 빌드 설정 참조를 참고하세요.
  3. 빌드를 클릭합니다.
  4. Unity Editor에서 AAB 파일을 다운로드합니다.

내부 테스트 버전 만들기

Play Console에서 내부 테스트 버전을 만들고 테스터를 추가하려면 다음 단계를 따르세요.

  1. Google Play Console에서 게임을 선택합니다.
  2. 테스트 및 출시 페이지 (테스트> 내부 테스트)로 이동합니다.
  3. 업로드를 클릭하고 AAB 파일을 선택합니다.
  4. 출시 세부정보 필드에 이름을 입력합니다.
  5. 다음을 클릭하고 발표곡 세부정보를 검토합니다.
  6. 저장 및 게시를 클릭합니다.

8. 프로젝트 빌드 및 실행

이제 프로젝트를 빌드하고 기기에서 테스트할 준비가 되었습니다.

  1. 게임이 열려 있는지 확인합니다.
  2. Play Console에서 File(파일) > Build Profile(빌드 프로필)(또는 Build Settings(빌드 설정))로 이동합니다.
  3. Play Console에 업로드하려면 Build App Bundle (Google Play)(App Bundle 빌드(Google Play))이 선택되어 있는지 확인하고, 연결된 기기에 직접 배포하려면 Build and Run(빌드 및 실행)을 클릭합니다.
  4. 폴더블 기기를 확인합니다. 기기의 접힌 상태 (예: HALF_OPENED, FLAT)와 화면 크기에 따라 게임 레이아웃을 즉시 조정해야 합니다.

9. 축하합니다

대형 화면 및 폴더블 기기에 맞게 Unity Android 게임을 조정하는 원리를 성공적으로 학습했습니다.

설문조사

이 Codelab에 대한 의견을 보내주시면 감사하겠습니다. 잠시 시간을 내어 설문조사에 참여해 주세요.