○はじめに
前回、固定解像度で各機種対応させましたが、黒い帯だったり狭いゲーム画面だったり、ちょっとダサいので、今回は全解像度に対応させて、全画面かつ全機種でプレイできるようにします。
前回の記事↓
○実行結果
こんな感じになります。
UIは機種に応じて場所を変化し、ゲームオブジェクトは画面内に収まるようにしています。
また、UIがiPhone12などの上部分のやつ(ノッチ)に隠れないような設定もしています。
また、実機で試してみると、ちゃんとノッチを避けてUIが配置されています。(色々あって上のGifとは構成が異なってます。ややこしくてすいません)
●リポジトリ
リポジトリです。Androidを持っている方は、ぜひ実機テストしてみてください。
※Unityバージョンは2021.3.8f1です。
インストールするのが面倒な方は、DeviceSimulatorを別途でインポートしてください。
○説明
●範囲内に収めるカメラ
CameraコンポーネントのorthographicSize
を機種の解像度に合わせて動的に変更しています。
現在の画面のアスペクト比と目標のアスペクト比から、orthographicSize
を求めます。
目標のアスペクト比:目標アス比のときのカメラサイズ = 現在のアスペクト比:orthographicSize
アスペクト比は、縦の解像度/横の解像度
で求まります。
●UI
RectTransform
のanchor
を、解像度とDeviceSimulatorのSafeArea
から求めます。
(※DeviceSimulator
をインポートする必要があります。)
●Canvas
また、CanvasScaler
コンポーネントは、ScaleWitfhScreenSize
に設定して、ReferenceResolution
に目的の解像度を設定してください。
○コード
●CameraResizer
機種に合わせてorthographicSize
を変更します。
[ExecuteAlways]
public class CameraResizer : MonoBehaviour
{
[SerializeField] Vector2 targetResolution;
[SerializeField] float targetOrthographicSize = 5;
Camera camera;
private void Start()
{
camera = GetComponent<Camera>();
}
private void Update()
{
ResizeCameraOrthographicSize();
}
void ResizeCameraOrthographicSize()
{
var currentResolution = new Vector2(Screen.width, Screen.height);
var targetAspect = targetResolution.x / targetResolution.y;
var currentAspect = currentResolution.x / currentResolution.y;
if (currentAspect >= targetAspect) {
camera.orthographicSize = targetOrthographicSize;
return;
}
var orthoGraphicSize = targetOrthographicSize * (targetAspect / currentAspect);
camera.orthographicSize = orthoGraphicSize;
}
}
Point💡
-
[ExecuteAlways]
属性で、再生していなくても更新処理をします。 targetRatio:targetCameraSize = currentRatio:size
(比例式)でorthographicSize
を求めます。(ここ↓)
var size = (targetCameraSize * currentRatio) / targetRatio;
●SetSafeArea
RectTramsform
のanchor
を変更します
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteAlways,RequireComponent(typeof(RectTransform))]
public class SetSafeArea : MonoBehaviour
{
RectTransform rect;
private void Awake()
{
rect = GetComponent<RectTransform>();
}
private void Update()
{
if (UnityEngine.Device.SystemInfo.deviceType == DeviceType.Handheld) {
var area = Screen.safeArea;
var resolution = Screen.currentResolution;
rect.sizeDelta = Vector2.zero;
rect.anchorMin = new Vector2(area.xMin / resolution.width, area.yMin / resolution.height);
rect.anchorMax = new Vector2(area.xMax / resolution.width, area.yMax / resolution.height);
}
else {
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.one;
}
}
}
Point💡
- if文の箇所で、デバイスの種類がスマホだったら(Simulatorビューがアクティブだったら)実装するようにしています。(ゲームビューでもセーフエリアを適用すると、UI表示がおかしくなるため。)
- その際、
SystemInfo
のnamespace
をUnityEngine.Device
にしないと、Editor上では正常に判定されません。(詳細)
- その際、
SafeArea/解像度
でanchor
を求めます。
○さいごに
Device Simulator、すごい便利です。
モバイルゲーム開発では必須といっても過言ではないかもですね!!!
また、UIについては、Androidに備わっている画面分割という機能にも対応しています。↓
折り畳みスマホの普及などで、画面分割機能は今後頻繁に使われそうなので、カメラについても画面分割に対応していきたいです。
●参考サイト