テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】Device Simulatorでノッチとセーフエリアの対策

f:id:tsubaki_t1:20191030233736j:plain

 Unity 2019.3で確認できるDevice Simulatorを使用して、ノッチやセーフエリアといった色々と面倒くさい問題の対策してみます。

Device Simulator

 Device Simulator はUnity 2019.3で追加されたパッケージです。このパッケージを使用するとエディター上でノッチの位置やセーフエリアの位置を大雑把に確認できる機能です。この機能の素晴らしい事はエディターでScreen.SafeAreaを確認出来る点です。この機能がなければ実際に動かさないと分からない部分も、この機能を使用することで確認することが出来ます。ということでSafeAreaやNotchの内容を確認して、安全な形でUIを構築してみます。

f:id:tsubaki_t1:20191030233853j:plain
被らない範囲を視覚的に確認できる

 また、この画面はGameViewであることから察せられる通り、普通に端末解像度やセーフエリアを維持しつつゲームを再生出来ます。ポップアップ等、ゲーム画面外にあるという前提で作成されている演出をSafeAreaコミコミで作ると正しく表示されないことがあるので、そのあたりも含めてよく確認するのが良さそうです。
 実際、ここで作成したUIはゲームにビルドしても想定通りに表示されました。

f:id:tsubaki_t1:20191030235843g:plain
DeviceSimulatorで調整した後にビルドしたもの。セーフエリア内でちゃんと表示出来ている

インストール

 Device Simulator のインストールはいつも通りのPackageManagerからです。現状はPreviewなのでShowPreviewPackageを有効にする必要があります。

f:id:tsubaki_t1:20191030223752p:plain
PackageManagerから選択してInstall

 パッケージ導入後はGameViewをSimulation Modeに切り替えます。これでGameViewが表示する内容を、ゲーム端末と同じ解像度、同じDPIに切り替えることが出来ます。またノッチの位置やピクセルが潰される位置をグラフィカルに表現してくれます。  その際にSafeAreaも使用可能にしてくれます。

f:id:tsubaki_t1:20191030223958g:plain
GameViewを切り替える

セーフエリア情報を元にUIを調整可能にする

f:id:tsubaki_t1:20191030223655j:plain

 ノッチの位置が確認できるぜヤッターだけでは片手落ちです。ノッチの位置や大きさは端末によって千差万別。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を配置出来ます。

https://user-images.githubusercontent.com/1644563/67865571-63e4ae80-fb1f-11e9-90f5-64b715e8b379.gif

f:id:tsubaki_t1:20191030234539j:plain
セーフエリアの範囲にRectTransformを調整

 なお、内部でアンカーを使用しているのは単純に「Canvas Scalerでサイズが調整されても問題なく動作する」事を保証するためです。

ノッチの範囲だけ回避したい

 ノッチの部分だけピンポイントで回避したい…という強気の場合はScreen.cutoutsが使用できます。ただしAndroidのCutoutの位置は必ずしも一つではない点に注意してください。ノッチは必ずしも上にある訳ではないですし、そもそもノッチという形をとっていない端末も存在します。またノッチが左右どちらかに偏っている場合もあります。

f:id:tsubaki_t1:20191031122549j:plain
おや、ノッチの位置が

 とはいえ、今回はノッチは上に一つだけあるという前提の実装です。

 例えば下のコードでノッチの左側と右側に一致する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);
    }
}

https://user-images.githubusercontent.com/1644563/67867527-73b1c200-fb22-11e9-973d-e4b52d619087.gif

f:id:tsubaki_t1:20191030235404j:plain
ノッチに被らない形でUIを配置

対応する端末が一覧に無い場合

 対応する端末が一覧に無い場合、ノッチの設定を自分で追加することも出来るみたいです。com.unity.device-simulator/com.unity.device-simulatorフォルダ内に設定と使用する画像ファイルがあり、コレを編集することで独自のレイアウト設定が作れます。

f:id:tsubaki_t1:20191030234018j:plain
セーフエリア・ノッチの設定と、その際に表示する描画範囲の画像

関連

blogs.unity3d.com

www.gaprot.jp

www.fast-system.jp