在前一篇的內容中提到OnApplicationPause和OnApplicationFocus兩個函式的功能,但最近在手機上做暫停時的資料存取時總會在某些狀況下出現bug,所以重新再研究了一下這兩個函式,找到了這篇文章:
Unity3d OnApplicationPause与OnApplicationFocus
在這裡就直接提重點概念,就像文章內容所提的:
暫停時會先呼叫OnApplicationPause再呼叫OnApplicationFocus。
回到應用程式時先呼叫OnApplicationFocus在呼叫OnApplicationPause。
首先驗證上述提到的這兩件事情是否是對的,以下是用來測試的腳本(PauseandFocusTest.cs)。
using UnityEngine; using System.Collections; using UnityEngine.UI; public class PauseandFocusTest : MonoBehaviour { public Text testText; private int testInt = 0; void OnApplicationPause(){ testText.text += DateTime.Now.ToString() + "Pause:" + testInt.ToString()+ "\n"; testInt++; } void OnApplicationFocus(){ testText.text += DateTime.Now.ToString() + "Focus:" + testInt.ToString()+ "\n"; testInt++; } }測試手機為遠傳的smart503版本為android 4.4.2,以及三星的SM-G720AX版本為android 4.4.4。
1. 首先在進入遊戲時觸發OnApplicationFocus。
2. 按下分頁或home鍵之後返回遊戲,暫停時Pause->Focus,返回遊戲時Focus->Pause,另外畫面鎖定在解鎖也包含在內。
3. 遊戲並沒有被暫停繼續在執行,但有其他手機的功能或指令覆蓋到遊戲前,當覆蓋到遊戲的功能或指令結束時呼叫Focus兩次,圖中包含飛航模式以下的功能全都在此範圍。
4. 最後提一個最麻煩的case,當螢幕自動關閉但沒有畫面鎖定,接著再返回遊戲。
smart503呼叫兩次Focus,SM-G720AX呼叫兩次Pause,smart503的情況透過計時器測試發現程式是有在繼續執行的,所以可以視為前面第3點提到的狀況,但SM-G720AX測試後並沒有繼續執行,看時間間隔執行的這兩次分別是在關閉及開啟時,從第2點去考慮視為中間兩次的Focus沒有呼叫到。
在這裡以我的狀況來做假設,OnApplicationPause做寫入資料,OnApplicationFocus做讀取資料,接著玩家做了以下的動作:
把遊戲暫停,在這個時間點做寫入資料後做讀取資料。
重新把遊戲開啟,在這個時間點做讀取資料後做寫入資料。
也就是說暫停時的讀取資料和遊戲重新開啟的寫入資料是不需要的,另外讀取資料前OnApplicationPause沒被呼叫過,則不做任何動作。
方法和上面文章作者韦斯利yx所寫的內容大致相同,在這裡只做些小修改和解說:
bool pauseState = false; bool focusState = false; void OnApplicationPause(){if(pauseState && !focusState){////(6) //讀取資料 pauseState = false; focusState = false; return; }if(!pauseState && !focusState){////(1) //寫入資料 } pauseState = true;////(2) if(pauseState && focusState){////(5) pauseState = false; focusState = false; } } void OnApplicationFocus(){ if(focusState){////(4) //讀取資料 } if (pauseState){////(3) focusState = true; } }
1. 首先在初始化時給定兩個布林變數pauseState和focusState,初始值為false。
(pauseState = false, focusState = false)
2. 接著當遊戲暫停時呼叫OnApplicationPause函式,因為(1)的條件pauseState和focusState為false成立所以做寫入資料,同時在(2)的地方pauseState被設定成true。
(pauseState = true, focusState = false)
3. 接著呼叫OnApplicationFocus,此時pauseState為true成立,所以(3)將focusState設定成true。
(pauseState = true, focusState = true)
4. 接下來返回遊戲呼叫OnApplicationFocus,(4)做讀取資料。
(pauseState = true, focusState = true)
5. 然後呼叫OnApplicationPause,在(5)的地方把pauseState和focusState設定回false。
(pauseState = false, focusState = false)
考慮到上面提到的兩次Focus,來看看單獨呼叫OnApplicationFocus兩次時,並不會有任何條件成立。
最後則是兩次Pause的狀況,在這裡就先當特殊情況處理,畢竟需要主動去呼叫OnApplicationFocus的內容,當OnApplicationPause被呼叫到時的當下會出現(pauseState = true, focusState = false)的狀況只有在連續兩次都是pause,在(6)的地方主動去讀取資料。
(PS:這部分我暫時沒有去處理,畢竟在讀取資料這部分要處理的太多,就算處理完也只是把三到五秒左右的時間差距補上,放置的時間在拉長後就會變成螢幕鎖定,連時間差距都會沒有,這裡就把布林變數重設成false,就把函式return掉就算了)
為了暫停返回的資料存取弄了快一個禮拜,結果在截圖當下bug就在眼前冒出來,還好後來有找到方法解決,目前開發中的作品暫時還沒測到其他bug,也祈禱以後不要冒出來,這次就到這裡了。
謝謝分享
回覆刪除