
유니티에서 노치 · 펀치홀 · 홈 막대에 UI 가 가리지 않게 하려면 Screen.safeArea 로 가리는 것이 없는 영역을 받아, UI 를 담은 부모 RectTransform 의 앵커를 그 영역에 맞춥니다. safeArea 는 화면 픽셀 단위라 화면 크기로 나눠 0~1 비율로 바꿔 넣습니다.
Rect area = Screen.safeArea; // 노치 · 홈 막대를 뺀 영역(픽셀)
Debug.Log("안전 영역 " + area + " / 화면 " + Screen.width + "x" + Screen.height);
에디터의 Game 창에서는 멀쩡하던 점수 표시가 휴대폰에 올리니 카메라 구멍에 걸리거나, 아래쪽 버튼이 홈 막대와 겹쳐 누르기 어려운 경우가 있습니다. 요즘 휴대폰은 화면 위에 노치나 펀치홀이 있고, 아래에는 제스처용 홈 막대가 있어서 화면 끝까지 UI 를 붙이면 일부가 가려집니다. Unity 에서는 Screen.safeArea 가 이런 것을 뺀 「안전 영역」 을 픽셀 단위 Rect 로 알려 줍니다. 이번 글에서는 이 영역에 맞춰 UI 부모의 앵커를 바꾸고, 화면이 돌아가면 다시 맞추는 SafeAreaFitter 를 만들겠습니다. 아래 광고 배너만큼 더 비우는 방법도 함께 보겠습니다.
C# (UNITY 3D)
SafeAreaFitter 가 없으면 점수 줄이 펀치홀 아래에, 시작 버튼이 홈 막대 아래에 깔립니다. 켜면 UI 부모의 앵커가 초록 점선(안전 영역)에 맞춰져 그 안으로 들어옵니다. 휴대폰을 가로로 돌리면 펀치홀이 왼쪽으로 가면서 safeArea 가 바뀌고, 다시 맞춰집니다.
1. 준비 — UI 를 담을 빈 부모 하나
Canvas 아래에 빈 오브젝트(UI (Canvas) > Panel 에서 Image 를 지워도 됩니다)를 하나 만들고 이름을 SafeArea 로 둡니다. 점수 · 버튼처럼 가려지면 안 되는 UI 는 모두 이 아래로 옮기고, 이 오브젝트에 SafeAreaFitter 를 붙입니다. 배경 그림처럼 화면 끝까지 채워야 하는 것은 SafeArea 밖(Canvas 바로 아래)에 둡니다.
using UnityEngine;
Screen 과 RectTransform 은 모두 UnityEngine 에 들어 있어서 using 은 하나면 됩니다.
2. 안전 영역 맞추기 코드
using UnityEngine;
//CodeFinder 코드파인더
//From https://codefinder.janndk.com/
[RequireComponent(typeof(RectTransform))]
public class SafeAreaFitter : MonoBehaviour
{
public float banner_bottom = 0f; // 아래에서 더 비울 높이(화면 픽셀 · 광고 배너 등)
Rect area_applied; // 마지막으로 맞춘 안전 영역
Vector2Int screen_applied; // 그때의 화면 크기
float banner_applied; // 그때의 배너 높이
void Update()
{
Rect area = Screen.safeArea;
Vector2Int screen = new Vector2Int(Screen.width, Screen.height);
if (area == area_applied && screen == screen_applied && banner_bottom == banner_applied)
return; // 바뀐 게 없으면 그대로
area_applied = area;
screen_applied = screen;
banner_applied = banner_bottom;
float bottom = Mathf.Min(area.yMax, area.yMin + banner_bottom); // 배너만큼 위로
Apply_SafeArea(Rect.MinMaxRect(area.xMin, bottom, area.xMax, area.yMax), screen);
}
public void Apply_SafeArea(Rect area, Vector2 screen)
{
if (screen.x <= 0 || screen.y <= 0)
return;
RectTransform rect = (RectTransform)transform;
rect.anchorMin = new Vector2(area.xMin / screen.x, area.yMin / screen.y); // 픽셀 → 0~1 비율
rect.anchorMax = new Vector2(area.xMax / screen.x, area.yMax / screen.y);
rect.offsetMin = Vector2.zero; // 앵커에 딱 붙임
rect.offsetMax = Vector2.zero;
}
}
앵커는 부모 크기에 대한 비율(0~1)이라서 safeArea 의 픽셀 값을 화면 너비 · 높이로 나눠 넣습니다. offset 을 0 으로 만들면 이 오브젝트가 앵커가 가리키는 사각형에 딱 맞게 펴집니다. safeArea 는 화면이 돌거나 창 크기가 바뀌면 달라지므로 Update 에서 값을 비교하다가 바뀌었을 때만 다시 맞춥니다. banner_bottom 은 처음에 0 이라 안전 영역 그대로 맞추고, 4절에서 아래 배너를 비울 때 씁니다.
이 스크립트는 Unity 6000.6.3f1 에서 컴파일 오류 없이 들어갔고, 배치 모드에서 예시 값(1080 x 2400 화면 · 위 120px · 아래 63px 가림)을 Apply_SafeArea 에 넣어 보니 anchorMin (0, 0.0263) · anchorMax (1, 0.95) 가 되었고, 1080 x 2400 부모 안에서 크기는 1080 x 2217 이었습니다. 실제 노치 폰에서 확인한 것은 아닙니다.
변수(variable)
banner_bottom(float) : 아래에서 더 비울 높이(화면 픽셀)
area_applied(Rect) : 마지막으로 맞춘 안전 영역
screen_applied(Vector2Int) : 그때의 화면 크기
banner_applied(float) : 그때의 배너 높이
함수(function)
Update : safeArea · 화면 크기 · 배너 높이 중 하나가 바뀌었을 때만, 배너만큼 아래를 줄인 영역으로 Apply_SafeArea 를 부릅니다.
Apply_SafeArea : 픽셀 영역을 0~1 비율로 바꿔 앵커에 넣고 offset 을 0 으로 맞춥니다.
3. 넣어 본 값으로 보기

세로일 때는 위아래만 줄어들고, 가로로 돌리면 펀치홀이 있는 왼쪽과 홈 막대가 있는 아래가 줄어듭니다. 노치가 없는 화면은 safeArea 가 화면 전체라서 앵커가 (0, 0) ~ (1, 1) 그대로입니다. RequireComponent 를 달아 두어서 빈 오브젝트에 붙여도 Transform 이 RectTransform 으로 바뀌었습니다.
4. 아래 배너만큼 더 비우기
fitter.banner_bottom = 168f; // 배너 높이(화면 픽셀) · 다음 Update 에서 다시 맞춤
화면 아래에 광고 배너가 붙는 게임은 버튼이 배너에 가리지 않도록 그 높이만큼 더 올립니다. 배너가 뜬 뒤 배너를 띄운 스크립트에서 banner_bottom 에 배너 높이(화면 픽셀)를 넣으면, 다음 Update 에서 안전 영역의 아래쪽을 그만큼 줄여 다시 맞춥니다. 예시 값에 168px 배너를 더하니 아래 앵커가 0.0263 에서 0.0963 으로 올라갔습니다. 배너 높이가 안전 영역보다 커도 Mathf.Min 으로 위쪽 끝을 넘지 않게 막았습니다.
5. 에디터에서는 그대로일 때 — 자주 하는 실수
Game 창에서는 아무 변화가 없다
보통의 Game 창에는 노치가 없어서 safeArea 가 화면 전체와 같습니다. 이 글을 확인한 배치 모드에서도 640 x 480 화면 전체가 나왔습니다. 노치가 있는 기기 모양으로 보려면 Game 창 위쪽에서 Simulator 로 바꿔 노치가 있는 기기를 고르거나, 실제 휴대폰에 올려 봅니다.
안드로이드 버전마다 다르다
Unity 문서에 따르면 safeArea 는 실제 화면이 아니라 앱 창을 기준으로 합니다. 안드로이드 14 이하에서 Player Settings 의 renderOutsideSafeArea 가 꺼져 있으면 Unity 가 창을 안전 영역으로 줄여서 safeArea 가 대개 화면 전체와 같고, 안드로이드 15(API 35)부터는 이 설정이 효과가 없습니다. 그래서 같은 게임도 휴대폰에 따라 가려지는 정도가 다를 수 있으니 SafeAreaFitter 를 붙여 두는 편이 안전합니다.
UI Toolkit 에서 쓸 때
safeArea 의 원점은 화면 왼쪽 아래입니다. 왼쪽 위를 원점으로 쓰는 UI Toolkit 에서는 y 를 뒤집어 써야 합니다. 이 글의 코드는 uGUI(Canvas) 기준입니다.
함께 보기: 휴대폰 화면 밝기와 꺼짐 방지는 유니티 안드로이드 화면 최대 밝기, 화면 꺼짐 방지 에 있습니다.
safeArea 동작은 Unity 공식 문서 Screen.safeArea 와 Unity 6000.6.3f1 에디터(Windows)에서 예시 값을 넣어 본 결과를 기준으로 적었습니다.
safeArea 에 맞춰 앵커를 바꾸고 아래 광고 배너만큼 더 비우는 처리는 제가 잰드케이로 낸 전광판 앱 BeamSay 의 홈 화면에서 실제로 쓰고 있습니다. PLAY 버튼이 배너에 가리지 않게 하려고 넣은 처리입니다(스토어 개발사 표시는 Jakadela Games).
'Unity3D > C#' 카테고리의 다른 글
| 유니티 안드로이드 뒤로가기 · 앱 종료 (KeyCode.Escape) (0) | 2026.10.30 |
|---|---|
| 유니티 앱 내릴 때 자동 저장 (OnApplicationPause) (0) | 2026.10.29 |
| 유니티 진동 울리기 · 진동 끄기 설정 (Handheld.Vibrate) (0) | 2026.10.28 |
| 유니티 프레임 60fps 고정 (targetFrameRate) (0) | 2026.10.27 |
| 유니티 데이터 저장 · 불러오기 (PlayerPrefs, HasKey) (0) | 2026.10.26 |