Android devices with a notch (display cutout) have recently become quite common. However, if you make a Unity application and deploy it to such device, by default Android OS will letter-box your app so that it the notch doesn't interfere with your UI.
If you want to make use of the whole display surface area and render in the area "behind" the notch, you need to add code to your application. Fortunately, since Unity 2018.3 there is a special option in the Player settings called "Render outside safe area" which does exactly this. If you want to have the same option in earlier versions of Unity - this plugin was made for you!
One advantage of this plugin over the built-in Unity solution is that it allows changing the setting in runtime if needed, by callingpublic void SetRenderBehindNotch(bool enabled)inRenderBehindNotchSupport.
If you are planning to make use of "rendering behind the notch" feature, you'll also need another feature which returns you the area of the screen which is outside of the notch area (and is safe to render to). The API is equivalent to whatScreen.safeAreaAPI does in newer Unity versions, and returns aRect.
This plugin is targeted towards Unity 2017.4, however I see no reasons why it shouldn't work with earlier versions too.
System Requirements
Tested on Unity 2017.4.28f1. Should work on any Unity version out there, but make sure your target API is set to 28 or higher. There is no point in using this plugin in Unity 2018.3 or later because these versions have notch support out of the box.
An Android device with Android 9 Pie or later. Some devices with earlier Android versions have notch/cutout, but Google has added a corresponding API only in Android 9. Feel free to add other vendor-specific bits of code to add support on earlier Androids at your own risk.
Usage
Copy the contents ofAssetsdirectory to your project
Attach theAssets/Scripts/RenderBehindNotchSupport.csscript to a game object of your choice in your first scene to make sure the plugin is loaded as early as possible
The script has a public boolean property so that you can tick/untick the checkbox to enable or disable rendering behind the notch with a single click
If you want to change the setting in runtime, callpublic void SetRenderBehindNotch(bool enabled)inRenderBehindNotchSupportclass.
Attach theAssets/Scripts/AndroidSafeArea.csscript to a game object of your choice if you need the safe area API. The propertyAndroidSafeArea.safeAreais returning aRect, use it to layout your UI.
Enjoy
Alternative solution
Instead of using the script (or if you want to apply the "render behind the notch" flag as early as possible), you could modify the theme used by Unity. To do so, please create a file at the pathAssets/Plugins/Android/res/values-v28/styles.xmlwith the following contents:
Unity 편집기에서 화면 크기를 iPhoneX와 같은 크기 (1125 × 2436)로 설정하면 Unity Player에서 디버그 할 수도 있습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;
public class SafeAreaScreen {
#if UNITY_IOS
[DllImport("__Internal")]
private extern static void GetSafeAreaImpl(out float x, out float y, out float w, out float h);
#endif
static public Rect GetSafeArea()
{
float x, y, w, h;
//初期値設定
x = 0;
y = 0;
w = Screen.width;
h = Screen.height;
#if UNITY_IOS && !UNITY_EDITOR
//iOSSafeAreasPluginを呼び出す
GetSafeAreaImpl(out x, out y, out w, out h);
#elif UNITY_ANDROID && !UNITY_EDITOR
//Androidの縦長端末対応が必要になったときのために
#else
//UnityエディタでiPhoneXのテストできるように値を設定する
if(Screen.width == 1125 && Screen.height == 2436 ){
y = 102;
h = 2202;
}
#endif
return new Rect(x, y, w, h);
}
static public int GetTopOffsetY(){
int offset = 0;
//画面の高さとセーフエリアの高さの差分
Rect screenSize = GetSafeArea();
if (Screen.height != screenSize.height) {
offset = Screen.height - (int)screenSize.height - (int)screenSize.y;
}
return offset;
}
static public int GetBottomOffsetY(){
int offset = 0;
//セーフエリアのyの位置取得
Rect screenSize = GetSafeArea();
if (Screen.height != screenSize.height) {
offset = (int)screenSize.y;
}
return offset;
}
}
NGUI의 SafeArea
NguiSafeAreaPatch.cs
SafeAreaScreen.cs에서 얻은 안전 영역을 바탕으로 Anchor의 위치를 조정합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NguiSafeAreaPatch : MonoBehaviour {
void Awake()
{
// UIAnchorを使ってAnchorを設定している場合
UIAnchor anchor = gameObject.GetComponent();
if(anchor != null){
//offsetの値を取得する
SetUIAnchorOffset(anchor);
return;
}
// UIRectをAnchorを使っている場合
UIRect rect = gameObject.GetComponent();
if (rect != null) {
//現在,NGUIのソースコードを解析中
//完成しだい公開予定
return;
}
}
private void SetUIAnchorOffset(UIAnchor anchor){
//現在のoffsetを取得する
Vector2 nowOffset = anchor.pixelOffset;
//TOP側の補正値取得
int topCorrectionOffset = SafeAreaScreen.GetTopOffsetY ();
//Bottom側の補正値取得
int bottomCorrectionOffset = SafeAreaScreen.GetBottomOffsetY ();
switch (anchor.side) {
case UIAnchor.Side.Top:
case UIAnchor.Side.TopLeft:
case UIAnchor.Side.TopRight:
anchor.pixelOffset.Set(nowOffset.x, nowOffset.y - topCorrectionOffset);
break;
case UIAnchor.Side.Bottom:
case UIAnchor.Side.BottomLeft:
case UIAnchor.Side.BottomRight:
anchor.pixelOffset.Set(nowOffset.x, nowOffset.y + bottomCorrectionOffset);
break;
}
}
}
사용법은이 소스 코드를 UIAnchor가 부착되어있는 게임 객체에 첨부 할뿐.
소스에서 무슨 일을하는지는 동작 환경이 iPhoneX 판정되면 스크린과 안전 영역의 높이의 차이를 계산하여 차등 분 게임 오브젝트를 낮 춥니 다.
델타 값은 UIAnchor의 "Pixel Offset"에 할당됩니다.
소스 코드를 반영한 결과
NguiSafeAreaPatch.cs을 UIAnchor에 연결시킨 결과를 기재합니다.
■ 반영 전
■ 반영 후
그 결과 안전 영역을 기준으로 할 수있었습니다.
이것으로 UIAnchor 대해서는 SafeArea의 대처가되었습니다.
그러나, 그 밖에도 「UIRect의 Anchor '에 대해서도 SafeAreas 대응이 있습니다.대응이 끝나는대로 수시 문서에 추가하는 것입니다.
배포시 가장 큰 골치덩어리중 하나는 AndroidManifest.xml 파일 수정문제일 것이다. Android Plugin을 만들어서 넣자니 짜증나고... 그럴때 간단하게 AndroidManifest.xml 파일을 수정할 수 있는 방법을 공개한다.
프로젝트 Root폴더에 보면 "Temp" 폴더가 생성되어 있을텐데 거길 가만히 보면 "StagingArea"라는 폴더가 보인다. 여기로 들어가면 다음과 같이 폴더가 구성되어 있다.
빌드에서 사용될 각종 Resource 파일들이 보일텐데 이중에 필요한건 AndroidManifest.xml 파일과 res 폴더 두개이다. 이 2개를 선택해서 CTRL+C 해서 복사하고 유니티로 돌아와서 "Plugins" 폴더를 만든다음 다시 "Android"폴더를 만들고 거기에 복사해 넣자.
이제 복사한 AndroidManifest.xml 파일을 열어서 마음대로 주무르면 됨. 끝!