個人的Unityおぼえがき 2024年7月14日号
ワタアメです。最近の気付きの備忘録です。
本文
Windows環境で、「Play中のものがの動いているか動いていないか」を判定したい場合はOnApplicationFocusではなくOnApplicationPauseを使った方がよさそう。
(理由:OnApplicationFocusはUnityエディタ上では「Gameビューに対するフォーカスの切り替え」の際に呼び出される。InscpectorとかHierarchyとかConsoleとかを触るとフォーカスがGameビューから外れ、「Play中のものが動いているがフォーカスなし」の状態が発生してしまうため)1. Play中に「何らかのフローティングウィンドウ(Unityエディタのメインウィンドウから切り離されたウィンドウ)」をクリックする
2. タスクバー、デスクトップ、Unityエディタ以外のウィンドウ等をクリックするなどしてUnityエディタのウィンドウを非アクティブにする
3. 何らかのフローティングウィンドウをクリックしてUnityエディタをアクティブにする
4. タスクバー、デスクトップ、Unityエディタ以外のウィンドウ等をクリックするなどしてUnityエディタのウィンドウを非アクティブにする
という手順を踏むと、バックグラウンド動作を許可しない設定(Run In Backgroundがfalseの状態)でも非アクティブ状態で動作が続くという現象(不具合?)が発生する。
この時、OnApplicationPauseは「1→2 (pause=true)」と「2→3 (pause=false)」のタイミングで呼び出されて、問題の「3→4」のタイミングでは呼び出されていないっぽい。
また、バックグラウンド動作を許可しない設定の時のUnityの音声についても「1→2」のタイミングで停止し「2→3」のタイミングで再開されるが(それはそう)、「3→4」のタイミングでは停止しない。
(どうやらバックグラウンド状態の判定に不具合がある?)
応用
バックグラウンド動作が無効の状態では、再生完了を含む停止状態や一時停止状態の時以外にも、再生中にバックグラウンドになった場合にもAudioSource.isPlayingがfalseになる。OnApplicationPauseから受け取った値を活用することで、falseになった原因が「再生停止や一時停止」と「バックグラウンド」のどちらであるかを識別することができる。
実装例
/* isFinished: 判定対象が既に停止している(再生完了によって停止した場合を含む)、
Stop()やPause()によって受動的に停止した場合はtrue
audioSource: 判定対象のAudioSourceの参照
isWindowPause: OnApplicationPauseから受け取った一時停止状況を保管しているbool型変数 */
bool isFinished = !audioSource.isPlaying && (Application.runInBackground || !isWindowPause);
これにAudioSourceのPlay()とかStop()とかPause()とかを呼び出す際に状態を保持する仕組みを併用すると「バックグラウンド処理が無効の環境下で再生完了をUpdateで検知する」といったことが可能になる。
環境
OS:Windows 10 Pro 22H2
Unity:2022.3.10f1
あとがき
実際のところ「応用」が本文だったりするけど、「本文」って書いてある方の内容もそれなりに重要かも。