1. 程式人生 > >【Unity】使用Time.timeScale暫停遊戲的時候的一些問題

【Unity】使用Time.timeScale暫停遊戲的時候的一些問題

使用Time.timeScale暫停遊戲的時候的一些問題

Unity版本:5.2(win7 64位測試)

Unity中游戲暫停一般使用Time.timeScale = 0 來實現。Time.timeScale = 0 即將遊戲執行的時間速度置為0,所以遊戲中一切東西都看上去不動了(FixedUpdate根據時間來執行,所以不會執行,但是Update和LateUpdate是繼續執行的,要想暫停Update和LateUpdate可以設定MonoBehaviour.enable = false)。

現在的需求是暫停遊戲的時候,角色正在釋放的效果是要繼續的,這些效果包括程式碼實現的效果和動畫實現的效果。來講講我遇到的坑

程式碼部分

  • DoTween忽略timeScale:很高興地用上了DoTween,我們可以設定Tweener.SetUpdate(true)來忽略timeScale,所以大部分問題就這麼歡快地解決了,在所有DoTween後面加上SetUpdate(true)。

  • DoTween對UI褪色的bug:但是當用DoTween對UI進行褪色處理時,遇到了問題:所有的UI都褪色了!當然這個問題我在上一篇部落格中已經講到了,這裡給出替代方案:CrossFadeAlpha這個函式的第三個引數是bool isIgnoreTimeScale,將第三個引數設定為true就行了。

  • WaitForSeconds

    :為了在遊戲暫停的時候延遲呼叫函式,使用了協程,StartCoroutine(某函式),攜程中呼叫的函式使用了WaitForSeconds,一開始以為是協程的問題,後來一番查閱,知道了是WaitForSeconds的問題,它應該是計的timescale影響的時間,所以遊戲暫停的時候不會執行,所以需要根據實際時間手動去實現:

IEnumerator HideLabel(GameObject labelPerfect, float waitTime, bool ignoreTimeScale = false)
    {
        if (ignoreTimeScale)
        {
            float
start = Time.realtimeSinceStartup; while (Time.realtimeSinceStartup < start + waitTime) { yield return null; } } else yield return new WaitForSeconds(waitTime); float destroyTime = 0.3f; labelPerfect.GetComponent<Text>().CrossFadeAlpha(0, destroyTime, true); Destroy(labelPerfect, destroyTime); }

動畫和例子效果部分

因為暫時只用到了Animator來實現動畫效果,所以這裡只講我遇到的Animator的忽略timeScale的方法,其他的可以參考雨鬆momo的文章

  • Animator忽略timeScale:網上介紹說是使用 “`
    Animator.updateMode = AnimatorUpdateMode.UnscaledTime; // 指定該Animator更新模式為不受scale影響
    我使用了這段程式碼,並且遊戲執行時面板中的Animator的UpdateMode屬性也確實變成了UnscaledTime,但是動畫還是暫停播放了,表示很無奈,這應該是這個版本Unity的bug吧。但是直接在面板中修改Animator的UpdateMode為UnscaledTime,動畫順利地在暫停狀態播放了。

發現了一個不錯的暫停遊戲的方法,來自candycat

如果一個物體需要一個暫停動作,例如停止動畫等等,可以讓它的指令碼實現OnPauseGame()函式,而在重啟時實現OnResumeGame() 函式。那麼暫停遊戲可以通過呼叫所有物件上的OnPauseGame()函式:

Object[] objects = FindObjectsOfType (typeof(GameObject));  
foreach (GameObject go in objects) {  
    go.SendMessage ("OnPauseGame", SendMessageOptions.DontRequireReceiver);  
}  

然後再呼叫OnResumeGame() 進行重啟。

一個基本的指令碼類似下面這樣:

protected bool paused;  

void OnPauseGame ()  
{  
    paused = true;  
}  

void OnResumeGame ()  
{  
    paused = false;  
}  

void Update ()  
{  
    if (!paused) {  
    // do movement  
    }  
}  

這樣方法有一個非常大的好處就是,你可以自己定製所有物體在暫停和重啟時的行為,例如儲存和載入資料等等。