
전광판 앱이나 QR 코드를 보여주는 화면, 운동 타이머처럼 화면을 오래 켜 두고 보는 앱에서는 두 가지가 꼭 필요합니다. 화면이 저절로 꺼지지 않아야 하고, 밖에서도 잘 보이도록 밝기를 최대로 올려야 합니다. 그런데 밝기를 바꾸려고 안드로이드 시스템 설정을 건드리면 「시스템 설정 변경」 권한을 따로 받아야 하고, 앱을 나간 뒤에도 밝기가 그대로 남아 버립니다. 안드로이드에는 앱 창 하나에만 적용되는 밝기 값(screenBrightness)이 있어서, 이 값을 쓰면 권한 없이 내 앱 화면만 밝게 만들 수 있고 앱을 나가면 원래 밝기로 돌아갑니다. Unity 에서는 AndroidJavaClass 로 이 값을 바꾸고, 화면 꺼짐은 Screen.sleepTimeout 으로 막을 수 있습니다. 이번 예시는 스크립트를 켜면 화면 꺼짐을 막고 최대 밝기로 올렸다가, 끄면 둘 다 시스템 설정을 따르게(밝기 -1 · SleepTimeout.SystemSetting) 돌려놓습니다. 앱이 그 전에 따로 정해 둔 값을 저장했다가 되살리지는 않습니다.
C# (UNITY 3D)
밝기를 바꾸는 부분은 어디서든 부를 수 있도록 static 클래스로 따로 만듭니다. 0~1 사이 값을 넣으면 그 밝기가 되고, -1 을 넣으면 시스템 밝기를 다시 따릅니다.
using UnityEngine;
//CodeFinder 코드파인더
//From https://codefinder.janndk.com/
public static class ScreenBrightness
{
// 시스템 밝기를 따른다는 값 (이름을 System 으로 지으면 안 됩니다 - 아래 주의 참고)
public const float FollowSystem = -1f;
public static void Set_Brightness(float value)
{
// 0 에 가까우면 화면이 꺼진 것처럼 보이는 기기가 있어 바닥을 둡니다
float brightness = value < 0f ? FollowSystem : Mathf.Clamp(value, 0.05f, 1f);
#if UNITY_ANDROID && !UNITY_EDITOR
try
{
var player = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
var activity = player.GetStatic<AndroidJavaObject>("currentActivity");
// 창 속성은 안드로이드 UI 스레드에서만 바꿀 수 있습니다
activity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
using (var window = activity.Call<AndroidJavaObject>("getWindow"))
using (var attributes = window.Call<AndroidJavaObject>("getAttributes"))
{
attributes.Set("screenBrightness", brightness);
window.Call("setAttributes", attributes);
}
}));
}
catch (System.Exception e)
{
// 밝기를 못 바꿨다고 앱이 멈추면 안 됩니다
Debug.LogWarning("밝기를 바꾸지 못했습니다: " + e.Message);
}
#endif
}
}
ScreenBrightness.cs 는 오브젝트에 붙이지 않아도 됩니다. 프로젝트 안에 파일만 있으면 됩니다.
다음은 실제로 화면을 지켜 주는 스크립트입니다. 화면을 켜 두어야 하는 화면(예: 재생 화면)의 오브젝트에 붙이면, 그 오브젝트가 켜질 때 최대 밝기 · 꺼짐 방지가 되고 꺼질 때 원래대로 돌아갑니다.
using UnityEngine;
//CodeFinder 코드파인더
//From https://codefinder.janndk.com/
public class ScreenKeeper : MonoBehaviour
{
void OnEnable()
{
Start_Keep();
}
void OnDisable()
{
Stop_Keep();
}
public void Start_Keep()
{
Screen.sleepTimeout = SleepTimeout.NeverSleep; // 화면 꺼짐 방지
ScreenBrightness.Set_Brightness(1f); // 최대 밝기
}
public void Stop_Keep()
{
ScreenBrightness.Set_Brightness(ScreenBrightness.FollowSystem); // 원래 밝기로
Screen.sleepTimeout = SleepTimeout.SystemSetting; // 기기 설정대로
}
}
함수(function)
Set_Brightness(float) : 앱 창의 밝기를 바꿉니다. 0.05~1 사이로 맞추고, 음수면 시스템 밝기를 따릅니다.
Start_Keep : 화면 꺼짐을 막고 최대 밝기로 올립니다.
Stop_Keep : 밝기와 화면 꺼짐을 시스템 설정을 따르게 돌려놓습니다.
변수(variable)
FollowSystem(float) : 시스템 밝기를 따르라는 값(-1). 안드로이드의 BRIGHTNESS_OVERRIDE_NONE 과 같은 값입니다.
brightness(float) : 실제로 창에 넣을 밝기 값입니다.
주의
1. 상수 이름을 System 으로 지으면 catch (System.Exception e) 의 System 이 그 상수로 읽혀서 컴파일 오류가 납니다. 이 부분은 #if UNITY_ANDROID 안에 있기 때문에 에디터에서는 아무 문제가 없다가 안드로이드로 빌드할 때만 오류가 납니다. 그래서 FollowSystem 처럼 겹치지 않는 이름을 씁니다.
2. 창 속성은 안드로이드 UI 스레드에서 바꾸는 것이라 runOnUiThread 로 보내 처리합니다. Unity 스크립트는 다른 스레드에서 돌기 때문에 이렇게 넘기는 게 안전합니다.
3. 에디터에서는 밝기가 바뀌지 않습니다. 실제 기기에 빌드해서 확인해야 합니다.
4. Screen.sleepTimeout 을 NeverSleep 으로 둔 채로 두면 배터리를 계속 씁니다. 필요한 화면을 벗어나면 꼭 SystemSetting 으로 돌려 놓습니다.
5. screenBrightness 는 이 앱 창에만 걸리는 값이라, 앱을 나가면 밝기가 시스템 값으로 돌아갑니다.
Unity 6000.3 (Unity 6.3) · 안드로이드 기준입니다. 시스템 밝기 설정은 건드리지 않기 때문에 AndroidManifest 에 권한을 추가할 필요가 없습니다.
이 코드는 제가 만든 전광판 앱 BeamSay 에서 쓰는 처리를 글에 맞게 두 클래스로 옮긴 것입니다. 옮긴 코드는 Unity 6000.3.14f1 Android 대상 컴파일에서 오류가 없었고, 기기에서는 앱 원본 코드로 확인했습니다.
'Unity3D > C#' 카테고리의 다른 글
| 유니티 떨어지는 이미지, 화면 벗어나면 자동 파괴 (0) | 2020.11.22 |
|---|---|
| Unity Cursor Tail (Instantiate, Destroy Delay) (0) | 2020.11.08 |
| Unity 클릭으로 오브젝트 생성, 파괴 (Instantiate/Destroy) (0) | 2020.11.07 |
| 유니티 2D LookRotation으로 클릭한 방향을 쳐다보게 하기 (4) | 2020.11.05 |
| 유니티 마우스 클릭 시 그 위치로 2D 오브젝트 이동시키기 (6) | 2020.11.04 |