代码改变世界

Unity3D之游戏暂停制作方法记录

2015-12-07 18:51  阿诚de窝  阅读(9392)  评论(0编辑  收藏  举报

在游戏开发中我们一般都需要涉及到一个功能:游戏暂停,但是这里指的暂停仅仅是核心模块的暂停,并不是整个游戏都暂停,比如一些UI和UI上的动画与特效是不能被暂停的,整个游戏都暂停了玩家该如何继续游戏呢。

这里我们主要讨论Unity的游戏暂停实现。

使用timeScale

我们通过设定Time.timeScale的值可以影响到整个游戏的播放速率。

但是请注意,无论timeScale是多少都不会影响到Update、LateUpdate这2个方法的执行速度,而是会影响到Time.time和Time.deltaTime的值。

比如将timeScale设定为0、1、2等等时,Update和LateUpdate的调用频率是不会变的,但是Time.time及Time.deltaTime会受其影响。

  • 当timeScale为0时,time为不继续累加时间,deltaTime为0;
  • 当timeScale为1时,time为正常累计时间,deltaTime为正常时间;
  • 当timeScale为2时,time为加倍累计时间,deltaTime为正常时间的两倍;

而对于物理方面的FixedUpdate则会由于timeScale的变换而影响到其调用的频率。

  • 当timeScale为0时,FixedUpdate将不会再被调用;
  • 当timeScale为1时,FixedUpdate正常按时间间隔调用;
  • 当timeScale为2时,FixedUpdate按两倍速度调用;

Time.realtimeSinceStartup

Time.realtimeSinceStartup可以不受timeScale的影响,其记录着程序启动到目前经过的时间。我们可以使用该属性来获得不受timeScale影响的时间。

不推荐使用timeScale来实现暂停

timeScale控制者整个游戏的时间缩放,修改它除了会影响到Time.time和Time.deltaTime外,还会影响到游戏的物理模拟,虽然诸如NGUI等支持ingoreTimeScale的属性,但是最好不使用timeScale = 0的方式来实现暂停。

同时timeScale还会影响到音乐播放及粒子效果,可以参考:http://www.xuanyusong.com/archives/2956

要实现慢动作播放等效果可以考虑使用timeScale,如果可以,最好自己实现一个timeScale,其只会影响到特定的模块,毕竟影响到全局的timeScale可能会造成一些难以察觉的坑。

 

我使用的暂停方法

由于我只需要暂停,不需要加速或慢速播放的效果,所以自己实现是最好的,如下:

 1 using UnityEngine;
 2 
 3 /// <summary>
 4 /// 支持暂停的 MonoBehaviour 基类.
 5 /// 游戏中需要暂停功能的逻辑都应该继承该类并将逻辑写到 OnUpdate 及 OnLateUpdate 方法中, 这两个方法在设置为暂停时不会被调用.
 6 /// </summary>
 7 public class PausingBehaviour : MonoBehaviour
 8 {
 9     /// <summary>
10     /// 是否暂停逻辑处理.
11     /// </summary>
12     public static bool pause { get; set; }
13 
14     static PausingBehaviour()
15     {
16         pause = false;
17     }
18 
19     private bool _isPaused;
20 
21     protected virtual void OnEnable()
22     {
23         _isPaused = pause;
24     }
25 
26     protected virtual void Update()
27     {
28         if(!pause)
29         {
30             if(_isPaused)
31             {
32                 _isPaused = false;
33                 this.OnPauseExit();
34             }
35 
36             this.OnUpdate();
37         }
38         else
39         {
40             if(!_isPaused)
41             {
42                 _isPaused = true;
43                 this.OnPauseEnter();
44             }
45         }
46     }
47 
48     /// <summary>
49     /// 可暂停的逻辑更新方法.
50     /// </summary>
51     protected virtual void OnUpdate()
52     {
53     }
54 
55     protected virtual void LateUpdate()
56     {
57         if(!pause)
58         {
59             this.OnLateUpdate();
60         }
61     }
62 
63     /// <summary>
64     /// 可暂停的逻辑更新方法.
65     /// </summary>
66     protected virtual void OnLateUpdate()
67     {
68     }
69 
70     /// <summary>
71     /// 暂停开始时会调用该方法.
72     /// </summary>
73     protected virtual void OnPauseEnter()
74     {
75     }
76 
77     /// <summary>
78     /// 暂停结束时会调用该方法.
79     /// </summary>
80     protected virtual void OnPauseExit()
81     {
82     }
83 }

所有需要暂停功能的脚本都继承自该类,帧逻辑写在OnUpdate及OnLateUpdate里,同时还有OnPauseEnter和OnPauseExit方法来表示是否进入和离开暂停状态。

当设定PausingBehaviour.pause = false时,OnUpdate及OnLateUpdate将不会被调用,而OnPauseEnter会被调用一次,这里可以对粒子效果等进行暂停,反之设定PausingBehaviour.pause = true时也一样。

手游强制暂停

这里额外提一下,手机游戏中来电话或锁屏或退出到桌面时,可以接受到Unity对应的事件,这里需要对游戏进行一下“强制暂停”,另外如果“强制暂停”时间过长,网络游戏有时得重新登录等事件。