자기개발/개발이야기

Unity3D에서 백그라운드 사운드 재생을 (완전 꼼수로) 하게 하는법

이 작업을 할때는 생활리듬이 개판이여서 근처 스터디카페를 가서 새벽에 작업하는 일이 많았다.
드립커피가 정말 맛있었다.

3줄요약

  • Android에서는 프로젝트 파일을 Export한 후, 소스코드를 일부 고쳐 Pause부분을 지운 후 빌드한다. (APK업로드방식이라 추후 다른 방법을 찾아야할 수 있음.)
  • IOS에서도 Export된 Xcode 프로젝트 파일에서 일부 코드를 수정해서 사운드 재생이 계속 되게 한다.
  • 단, IOS에서는 코드 외의 빌드 설정도 수정할 필요가 있다.

(이하 AOS = Android OS)

개요

어찌저찌해서 어플리케이션 외주를 하게 되었다. 특정 타이밍에 유저 액션을 받거나 이미지를 보여주거나 하는 프로그램이었다. 웹으로 하지 않았으면 하고, 동영상으로 하기에는 인터렉티브 요소 등 별개 프로그램으로 작성이 필요한 요구사항이 있었다.

그래서, 규모가 작음 + IOS와 AOS 둘다 지원 + 미디어 관련 요구사항이 많음 + 내가 유니티를 잘 함 같은 요소가 합쳐져서 개발을 Unity3D로 진행하기로 했다.

사실 어느정도의 요구사항 변경은 당연히 예상했기에, 싱글벙글하면서 유연성있게 작성해서 프로토타입을 보여드렸다.
그 때, 프로토타입을 보고 만족하시더니 이런 말을 하셨다.

혹시 앱 실행중이 아닐때도 사운드를 재생할 수 있나요?

아뿔싸! 간단한 앱이라서 백그라운드 처리는 없겠지 싶었던 내 어리짐작이 문제였다. 일반 사용자 입장에서 중요한건 간단해보이는 것이지 실제 구현 난이도가 중요한게 아니였다. Unity3D로 했으니 백그라운드 처리가 제한적이라 생각하는 것 자체가 이미 Unity를 좀 아는 사람이 아니면 생각할 수 없는 것이었다.

이야기를 조금 나눠보니, 이 요구사항은 상당히 중요한 요구사항이었다. Flutter나 그런 것으로 앱을 다시 짜기는 죽도록 싫었던 나는 "까짓것 한번 해보죠" 하고 날로 먹을 수 있는 방법이 없나 찾아보기 시작했다.

우선 깔고 시작하자면, Run in background 설정은 PC에서만 적용되는거라 모바일에서는 아무 의미 없으므로, 이걸 체크하라는 글은 다 걸러도 된다.

Android의 경우

굉장히 쉽게 찾았고 허무했다. AOS상에서 유니티는 Activity(안드로이드 용어. 몰라도됨) 위에서 돌아가는데, 이것이 유니티에 이리저리 이벤트를 주는 식으로 되어있다. 여기서 앱이 백그라운드로 갈때 Pause 처리를 해주는 코드가 있는데, 이 코드를 주석처리해서 빌드하면 Pause시 아무런 이벤트가 발생하지 않아 음악이 그대로 재생된다...

물론 Pause 이벤트가 아에 발생하지 않으므로 여기서 이런저런 처리를 하고 있다면 곤란할듯... 나는 아무것도 해주지 않아서 여기서 검색을 멈췄다.

https://answers.unity.com/questions/1496424/how-can-i-make-music-player-running-in-background.html

IOS의 경우

2개를 해줘야한다

  1. AVAudioSession이 백그라운드 재생을 허용하게 UnityAppController.mm 파일을 수정
    - (void)startUnity:(UIApplication*)application 함수의 마지막에 AVAudioSession 관련 설정해주는 코드가 있는데, 이 코드를 변경한다.다음 링크를 참고했다.
  2. https://forum.unity.com/threads/enable-custom-background-behaviors-not-working-at-least-on-ios.990023/
  3. IOS Player Setting에서 IOS Background Mode에서 관련 설정 활성화(Fetch는 혹시 몰라서 체크했음.)

이렇게 할 경우, 사운드는 계속 재생되지만 Update 함수가 콜 되지 않는다. 유니티 메인 스레드가 멈추는 것으로 보인다. 다른 스레드에서 돌리는 방법으로 해소해야되는데, 유니티 내장 함수는 메인 스레드에서만 호출되니까 사실상 할 수 있는 일이 제한된다.

  • 할 수 있는 일이 한정적이라는 것을 알아야할것이다...

그래서 사실 Update 함수에서 검사해서 타이밍에 맞게 사운드를 재생시키는 코드가 있었는데, 백그라운드에서는 Update 함수 콜이 안되니 타이밍이 되도 사운드가 재생이 안되었다. 그래서 타이밍에 맞게 재생시키기 위해 위해 통짜 사운드 파일 하나 만들어서 재생하는 식으로 변경했다. (Audacity 짱짱)

그 외에 알아야할 점

IOS는 깐깐해서 프로젝트 설정도 바꿔서 올려줘야한다. (애플 심사때 이 앱이 왜 이 권한을 사용하는지 물어본다 ㅎㄷㄷ)

Audio 하고 Fetch 권한을 체크해준다. (참고 : https://docs.unity3d.com/ScriptReference/iOSBackgroundMode.html)

결론

유니티는 백그라운드에서 뭘 하는 것이 힘드니, 유니티로 제작할때는 이를 염두해두자.
그리고, 이 방법은 야매니 이런 요구사항이 구체적으로 들어온다면 엔진(개발환경) 변경을 고려하던가 IOS/AOS 네이티브 함수를 콜 해서 대응하자. (라이브러리가 있을지도?)