Unity 2019.3で確認できるDevice Simulatorを使用して、ノッチやセーフエリアといった色々と面倒くさい問題の対策してみます。
Device Simulator
Device Simulator
はUnity 2019.3で追加されたパッケージです。このパッケージを使用するとエディター上でノッチの位置やセーフエリアの位置を大雑把に確認できる機能です。この機能の素晴らしい事はエディターでScreen.SafeAreaを確認出来る点です。この機能がなければ実際に動かさないと分からない部分も、この機能を使用することで確認することが出来ます。ということでSafeAreaやNotchの内容を確認して、安全な形でUIを構築してみます。
また、この画面はGameViewであることから察せられる通り、普通に端末解像度やセーフエリアを維持しつつゲームを再生出来ます。ポップアップ等、ゲーム画面外にあるという前提で作成されている演出をSafeAreaコミコミで作ると正しく表示されないことがあるので、そのあたりも含めてよく確認するのが良さそうです。
実際、ここで作成したUIはゲームにビルドしても想定通りに表示されました。
インストール
Device Simulator
のインストールはいつも通りのPackageManagerからです。現状はPreviewなのでShowPreviewPackageを有効にする必要があります。
パッケージ導入後はGameViewをSimulation Modeに切り替えます。これでGameViewが表示する内容を、ゲーム端末と同じ解像度、同じDPIに切り替えることが出来ます。またノッチの位置やピクセルが潰される位置をグラフィカルに表現してくれます。 その際にSafeAreaも使用可能にしてくれます。
セーフエリア情報を元にUIを調整可能にする
ノッチの位置が確認できるぜヤッターだけでは片手落ちです。ノッチの位置や大きさは端末によって千差万別。iPhoneのように殆ど画面上をノッチが埋めている端末もあれば、幾つかのAndroid端末のようにほんの少ししかノッチで埋めていない端末もあります。セーフエリアの位置も色位rと微妙に違います。なので、セーフエリアの位置を元にUIを調整出来る方法を考えてみます。
まずセーフエリアの位置を元にUIを配置します。UIの場合、親のRectTransfromのサイズSafeAreaの大きさに調整してやれば概ね問題は解決します。アンカーの位置さえ調整すれば良いわけですから。ということで、親となるRectTransformのサイズをSafeAreaの位置に合わせます。この時、RectTransformのLeft、Rightは0にしてください。
using UnityEngine; [RequireComponent(typeof(RectTransform))] [ExecuteAlways] public class SafeAreaPadding : MonoBehaviour { private DeviceOrientation postOrientation; void Update() { if (Input.deviceOrientation != DeviceOrientation.Unknown && postOrientation == Input.deviceOrientation) return; postOrientation = Input.deviceOrientation; var rect = GetComponent<RectTransform>(); var area = Screen.safeArea; var resolition = Screen.currentResolution; rect.sizeDelta = Vector2.zero; rect.anchorMax = new Vector2(area.xMax / resolition.width, area.yMax / resolition.height); rect.anchorMin = new Vector2(area.xMin / resolition.width, area.yMin / resolition.height); } }
このコードをCanvas直下の適当なRectTransformに設定すれば、RectTrasnfromはSafeAreaの大きさになります。あとはSafeAreaのサイズになったUIの子としてアンカーを調整してやれば、セーフエリア内を出ない形でUIを配置出来ます。
なお、内部でアンカーを使用しているのは単純に「Canvas Scalerでサイズが調整されても問題なく動作する」事を保証するためです。
ノッチの範囲だけ回避したい
ノッチの部分だけピンポイントで回避したい…という強気の場合はScreen.cutouts
が使用できます。ただしAndroidのCutoutの位置は必ずしも一つではない点に注意してください。ノッチは必ずしも上にある訳ではないですし、そもそもノッチという形をとっていない端末も存在します。またノッチが左右どちらかに偏っている場合もあります。
とはいえ、今回はノッチは上に一つだけあるという前提の実装です。
例えば下のコードでノッチの左側と右側に一致するRectTransformを構築します。これにより、ノッチ外の部分のUIを構築出来ます。あとはRectTransformのサイズをはみ出ないようにUIを実装すれば、ノッチでUIが隠れるといった事を回避出来ます。
using UnityEngine; [ExecuteAlways] public class NotchPadding : MonoBehaviour { [SerializeField] RectTransform left, right; void Update() { if (Screen.cutouts[0] == null || left == null || right == null) return; var resolition = Screen.currentResolution; left.anchorMin = new Vector2(0, Screen.cutouts[0].yMin / resolition.height); left.anchorMax = new Vector2(Screen.cutouts[0].xMin / resolition.width, 1); right.anchorMin = new Vector2(Screen.cutouts[0].xMax / resolition.width, Screen.cutouts[0].yMin / resolition.height); right.anchorMax = new Vector2(1, 1); } }
対応する端末が一覧に無い場合
対応する端末が一覧に無い場合、ノッチの設定を自分で追加することも出来るみたいです。com.unity.device-simulator/com.unity.device-simulator
フォルダ内に設定と使用する画像ファイルがあり、コレを編集することで独自のレイアウト設定が作れます。