秒でセーフエリア対応する

要は Screen.safeArea に親 RectTransform を合わせればいいんだけど、ググると回りくどい方法しか出てこないので。

対応

 1. Canvas と UI の間に Container 的なオブジェクトを一段噛ませる

f:id:eiki_okuma:20200624190855p:plain

 2. そのContainerに以下のスクリプトを貼っ付ける

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SafeAreaAdjuster : MonoBehaviour
{
    private void Awake()
    {
        var panel = GetComponent<RectTransform>();
        var area = Screen.safeArea;

        var anchorMin = area.position;
        var anchorMax = area.position + area.size;
        anchorMin.x /= Screen.width;
        anchorMin.y /= Screen.height;
        anchorMax.x /= Screen.width;
        anchorMax.y /= Screen.height;
        panel.anchorMin = anchorMin;
        panel.anchorMax = anchorMax;
    }
}

 3. Container 以下の UI は画面のアスペクト比がどんなものでもちゃんと対応できるようにしておく

 4. 終わり

解説

 Screen.safeArea は実解像度サイズで指定されるが、多くの場合 Canvas Scaler はScale with Screen Size を使っているので、anchorMin / anchorMax を使う必要がある。もう少しスマートに書けないか粘ったが、結局この部分はみんなが使っているものと同じ。

注釈

※1:もう作ってしまったゲームに後から対応する場合でも、意外と各 UI をバインドする箇所で Root を差し替えればいいだけなので工数は大きくない。むしろ、これで工数が異常にでかい場合は UI の作り方が悪い。
※2:回りくどい方法、と言ったがこのコードはビルドしないと確認できないので、PC上で色んな環境のテストをしたい場合は先人の知恵を借りるのが一番。
※3:~2018.4.24 で起動直後の Awake で safeArea が NaN になるバグあり。2019LTS では修正済み。2018.4.25 で修正されるらしい。