【Unity/iOS】iPhoneXのSafeArea対応

iPhoneXは上部にセンサーハウジング(凹)や角丸があるため、矩形の領域(SafeArea)を考慮する必要があります。

SafeAreaについては以下を参照
Update Apps for iPhone X - iOS - Apple Developer

この記事では縦で使用する場合を想定しています。

f:id:chocolattips:20180207083147p:plain

SafeAreaの取得

Unity5.5.x - 2017.x

iOSの場合

float x, y, w, h;
GetSafeAreaImpl(out x, out y, out w, out h);
var safeArea = new Rect (x, y, w, h);

iOS以外の場合

var safeArea = new Rect(0, 0, Scree.width, Scree.height);

2017.3から

2017.3からはScreenから取れるようですが、未検証です。

var safeArea = Screen.safeArea;

SafeAreaを反映

以下のようにCanvas直下にGameObject(Content)を配置します。

Canvas/
    Content/

ContentがSafeArea内になります。 もし、現在Canvas直下にUIを配置している場合は、Content内に入れるように1つ階層を下げる必要がありますが、画面全体を覆うようなエフェクト処理は今まで通りCanvas直下で問題ありません。

また、縦型の場合、以下のようにContentの上下に配置すると便利だったりします。

Canvas/
    Top/
    Content/
    Bottom/
  • f:id:chocolattips:20180206084554p:plain iPhoneX
  • f:id:chocolattips:20180206084549p:plain iPhoneX以外

Top、BottomがContentの外側になります。iPhoneX以外ではTop, Bottomは使用しません(サイズがゼロまたはactiveSelf==false)。 TopとBottomは状況に応じてHeader/Footerの色で塗りつぶしたり、非表示にするといった対応が必要になります。

ContentにSafeAreaを反映

ダウンロードしたパッチのAssets/SetCanvasBounds.csApplySafeAreaを使用します。 Canvasスクリプトを追加し、StartのタイミングでApplySafeAreaのpanel部分をContentに置き換えて反映します。

Top/Content/Bottomのサイズを設定

SafeAreaは左下基準で取得するため、 bottomの高さがsafeArea.y、topの高さがScreenからsafeAreaとbottomの高さを引いたものになります。

void _ApplyLayout(){
    var safeArea = SafeArea.GetSafeArea ();
    SafeArea.ApplySafeArea (_content, safeArea);

    var scale = 1 / _content.lossyScale.y;

    var bottomSize = _bottom.sizeDelta;
    bottomSize.y = _bottom.gameObject.activeSelf ? safeArea.y * scale : 0;
    _bottom.sizeDelta = bottomSize;

    var topSize = _top.sizeDelta;
    topSize.y = _top.gameObject.activeSelf ? (Screen.height - safeArea.height - safeArea.y) * scale : 0;
    _top.sizeDelta = topSize;
}

ただ、このままでは実機でなければ確認ができず、大変不便です。

Editor上で確認

開発しやすくするために、Editor上でも確認できるようにしておくと便利です。 SafeAreaのrectに対し、以下のように変更します。 (要Window > Gameのwidth=1125, height=2436に設定)

#if UNITY_EDITOR
    if(Screen.width == 1125 && Screen.height == 2436){
        rect.y = 102;
        rect.height = 2202;
    }
#endif

参考