안녕하세요.
유니티 SDK 나오기 전에 안드로이드에서 실기기 테스트할 때, 백그라운드로 가도 소리가 재생되는 현상을 처리하는 코드를 공유드립니다.
이 토픽의 댓글을 기반으로 몇가지 빠져있는 부분과 좀 더 친절하게 작성한 코드입니다.
전부 유니티 안에서 처리할 수 있고, 두 개의 파일만 있으면 됩니다.
1. 먼저 ObserveVisibilityPlugin.jslib 파일을 만들어유니티 Assets 폴더 아래에 Plugin/WebGL 폴더에 넣습니다.
당연히 WebGL 플랫폼만 Include 해주시면 됩니다.
플러그인 내용은 아래 코드를 붙여넣어주세요.
// ObserveVisibilityPlugin.jslib
mergeInto(LibraryManager.library, {
StartObserveVisibility: function (goPtr, methodPtr) {
var goName = UTF8ToString(goPtr);
var method = UTF8ToString(methodPtr);
// 이전 구독 해제
if (typeof window.__tossVisUnsub === 'function') {
try { window.__tossVisUnsub(); } catch (e) { console.log(e); }
window.__tossVisUnsub = null;
}
function send(state, evt) {
var payload = JSON.stringify({
state: state, // "visible" | "hidden"
eventType: evt, // "visibilitychange" | "pagehide" | "pageshow" | "blur" | "focus" | "init"
hidden: state === 'hidden',
ts: Date.now()
});
console.log(`[TOSS] ${goName} ${method} ${payload}`);
try { SendMessage(goName, method, state === 'hidden' ? 1 : 0); } catch (e) { console.log(e); }
}
// 캡처 단계로 가장 먼저 잡는다(숨기기 직전에도 최대한 빨리 유니티 호출)
var opts = { capture: true, passive: true };
function onVisibility() { send(document.hidden ? 'hidden' : 'visible', 'visibilitychange'); }
function onPageHide() { send('hidden', 'pagehide'); }
function onPageShow() { send('visible', 'pageshow'); }
function onBlur() { send(document.hidden ? 'hidden' : 'visible', 'blur'); }
function onFocus() { send(document.hidden ? 'hidden' : 'visible', 'focus'); }
function onFreeze() { send('hidden', 'freeze'); }
// 이벤트 구독
document.addEventListener('visibilitychange', onVisibility, opts);
window.addEventListener('pagehide', onPageHide, opts);
window.addEventListener('pageshow', onPageShow, opts);
window.addEventListener('blur', onBlur, opts);
window.addEventListener('focus', onFocus, opts);
window.addEventListener('freeze', onFreeze, opts);
// 초기 1회 상태 통지(필요 시)
send(document.hidden ? 'hidden' : 'visible', 'init');
// 이벤트 구독 해제 함수 정의
window.__tossVisUnsub = function () {
document.removeEventListener('visibilitychange', onVisibility, opts);
window.removeEventListener('pagehide', onPageHide, opts);
window.removeEventListener('pageshow', onPageShow, opts);
window.removeEventListener('blur', onBlur, opts);
window.removeEventListener('focus', onFocus, opts);
window.removeEventListener('freeze', onFreeze, opts);
};
}
});
2. 이제 상태가 변경될 때 소리를 토글할 C#스크립트에 아래 코드를 추가합니다. 새로 생성해도 무방합니다.
public class BGMPlayer : MonoBehaviour
{
[DllImport("__Internal")]
private static extern int StartObserveVisibility(string goName, string methodName);
private void Awake()
{
StartObserveVisibility(transform.GetHierarchyPath(), nameof(OnVisibleStatusChanged));
}
public static string GetHierarchyPath(Transform transform)
{
List<string> path = new List<string>();
Transform current = transform;
while (current != null)
{
path.Add(current.name);
current = current.parent;
}
path.Reverse();
return string.Join("/", path);
}
private void OnVisibleStatusChanged(int pauseStatus)
{
if (pauseStatus == 1)
{
AudioListener.pause = true;
Time.timeScale = 0f;
Debug.Log("앱 백그라운드 - 오디오 일시정지");
}
else
{
AudioListener.pause = false;
Time.timeScale = 1f;
Debug.Log("앱 포그라운드 - 오디오 재개");
}
}
}
생성한 C# 스크립트를 씬 어딘가에 게임오브젝트를 만들어 붙여넣어주시면 됩니다.
(당연히 이 게임오브젝트는 삭제되면 안 됩니다.)
이제 빌드 후 실행해보시면 잘 처리되는 걸 볼 수 있습니다.
감사합니다.
