2015年3月30日 星期一

【Unity】OnApplicationPause、OnApplicationFocus測試2

(內容不完整的前篇)
在前一篇的內容中提到OnApplicationPauseOnApplicationFocus兩個函式的功能,但最近在手機上做暫停時的資料存取時總會在某些狀況下出現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。
OnApplicationPause OnApplicationFocus test

2. 按下分頁或home鍵之後返回遊戲,暫停時Pause->Focus,返回遊戲時Focus->Pause,另外畫面鎖定在解鎖也包含在內。
OnApplicationPause OnApplicationFocus test

用側拍而不是手機截圖請見諒,接下來是為什麼要用側拍的原因:
3. 遊戲並沒有被暫停繼續在執行,但有其他手機的功能或指令覆蓋到遊戲前,當覆蓋到遊戲的功能或指令結束時呼叫Focus兩次,圖中包含飛航模式以下的功能全都在此範圍
OnApplicationPause OnApplicationFocus test

4. 最後提一個最麻煩的case,當螢幕自動關閉但沒有畫面鎖定,接著再返回遊戲。
OnApplicationPause OnApplicationFocus test

OnApplicationPause OnApplicationFocus test

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,也祈禱以後不要冒出來,這次就到這裡了。


1 則留言:

【自製小遊戲】水平思考猜謎(海龜湯)

遊戲連結 海龜湯的玩法是由出題者提出一個難以理解的事件,參與猜題者可以提出任何問題以試圖縮小範圍並找出事件背後真正的原因。但出題者僅能以「是」、「不是」或「沒有關係」來回答問題。 本遊戲蒐集各種論壇、平台的42個題目,提供給想玩海龜湯卻愁找不到題目的你們。 ...