zoukankan      html  css  js  c++  java
  • Unity Time.timeScale

    原创网址: http://www.xuanyusong.com/archives/2956  

    项目里面一直在用Time.timeScale来做游戏的 1倍 2倍整体加速,今天我仔细看了一下Time.timeScale才发现之前我理解错了一些东西。

    Time.timeScale可以控制Update 和LateUpdate 的执行速度,举个例子说明一下。

    Time.timeScale=1时(默认值),Update、LateUpdate、FixedUpdate 都按正常的时间来执行。

    Time.timeScale=2时,Update和 LateUpdate的执行速度是之前的2倍,而FixedUpdate还是按正常时间来执行。

    Sorry上面红色这部分确实是写错了,感谢网友在留言处给我的指正,谢谢。

    正确的应该是timeScale不会影响Update和LateUpdate的执行速度。因为FixedUpdate是根据时间来的,所以timeScale只会影响FixedUpdate的速度。 再次抱歉。。 谢谢热心网友给我的指正。。 因为我的项目里在处理战斗部分的时候 大量使用 iTween 所以  2  3 倍加速 或者暂停 的功能直接修改timeScale 。 

    Time.timeScale也误导了我很久,为什么这么说呢?我原先一直以为Time.timeScale = 0 的话所有的Update都不执行了。今天测试了一下发现原来不是这样的,无论Time.timeScale 等于多说Update和LateUpdate都会去执行,不信你可以自己做个实验看看。

    Time.timeScale还会影响Time.time的时间,比如Time.timeScale = 2的话,那么Time.time的增长速度也会变成2倍速度。如果你想取到游戏的实际时间,那么使用Time.timeSinceLevelLoad就可以,前提是必须在Awake()方法以后再取,如果在Awake()方法里面取Time.realtimeSinceStartup会取出一个错误的值,在Start方法里面取的话就正常了。

    总之一句话Time.timeScale影响的是Unity的游戏时间缩放比例。Unity里面所有跟时间有关系的东西都是根据timeScale来演算的。仔细想想现在的手游就是个 动画 和 粒子技能特效 还有UI位移特效,所以改他们的速度直接用Time.timeScale就可以完成。还有一个重要的东西就是人物移动 或者 技能移动的速度了, 根据时间的公式,时间 = 路程速度 ,比如角色从起点跑到中间的一个预期时间, 或者一个技能的火球从攻击到打中目标的预期时间。 凡是处理时间的东东全用Time.time 这样就可以完美让Time.timeScale控制你的游戏了。

    下面说说两个大家伙比较关心的话题。

    1.游戏暂停

    设置 Time.timeScale = 0;即可让游戏暂停。 其实我们暂停的主要是 人物动画,还有技能特效,比如一个火球打了一半。UI方面往往我们不希望暂停,比如暂停界面 有一些UI位移动画或者帧动画, 或者最起码要有个“取消暂停的按钮” 吧。 总不能游戏暂停了我点击按钮 按钮的点击动画 或者特效也暂停了吧。

    所有的动画都是基于时间来的,因为Time.timeScale = 0了,所以Time.time也就不会在变化了。换句话来说如果游戏暂停以后想在暂停界面上继续播放一些不受Time.timeScale 影响的动画,那么我们就需要用到Time.realtimeSinceStartup

    如果你的项目NGUI的版本还算比较新的话,你会发现在UITweener.cs处理UI动画的基类里面已经增加了一个属性叫public bool ignoreTimeScale = true; 它就是控制控制NGUI 的UI动画是否受到ignoreTimeScale影响。如下图所示,你可以看看NGUI在Update里面的实现,它也是根据时间来判断的。忽略timescale的话就用真实时间,不忽略的话就用Time.time 和Time.deltaTime。

    项目里面一直在用Time.timeScale来做游戏的 1倍 2倍整体加速,今天我仔细看了一下Time.timeScale才发现之前我理解错了一些东西。

    Time.timeScale可以控制Update 和LateUpdate 的执行速度,举个例子说明一下。

    Time.timeScale=1时,Update、LateUpdate、FixedUpdate 都按正常的时间来执行。

    Time.timeScale=2时,Update和 LateUpdate的执行速度是之前的2倍,而FixedUpdate还是按正常时间来执行。

    Sorry上面红色这部分确实是写错了,感谢网友在留言处给我的指正,谢谢。

    正确的应该是timeScale不会影响Update和LateUpdate的执行速度。因为FixedUpdate是根据时间来的,所以timeScale只会影响FixedUpdate的速度。 再次抱歉。。 谢谢热心网友给我的指正。。 因为我的项目里在处理战斗部分的时候 大量使用 iTween 所以  2  3 倍加速 或者暂停 的功能直接修改timeScale 。 

    Time.timeScale也误导了我很久,为什么这么说呢?我原先一直以为Time.timeScale = 0 的话所有的Update都不执行了。今天测试了一下发现原来不是这样的,无论Time.timeScale 等于多说Update和LateUpdate都会去执行,不信你可以自己做个实验看看。

    Time.timeScale还会影响Time.time的时间,比如Time.timeScale = 2的话,那么Time.time的增长速度也会变成2倍速度。如果你想取到游戏的实际时间,那么使用Time.timeSinceLevelLoad就可以,前提是必须在Awake()方法以后再取,如果在Awake()方法里面取Time.realtimeSinceStartup会取出一个错误的值,在Start方法里面取的话就正常了。

    总之一句话Time.timeScale影响的是Unity的游戏时间缩放比例。Unity里面所有跟时间有关系的东西都是根据timeScale来演算的。仔细想想现在的手游就是个 动画 和 粒子技能特效 还有UI位移特效,所以改他们的速度直接用Time.timeScale就可以完成。还有一个重要的东西就是人物移动 或者 技能移动的速度了, 根据时间的公式,时间 = 路程速度 ,比如角色从起点跑到中间的一个预期时间, 或者一个技能的火球从攻击到打中目标的预期时间。 凡是处理时间的东东全用Time.time 这样就可以完美让Time.timeScale控制你的游戏了。

    下面说说两个大家伙比较关心的话题。

    1.游戏暂停

    设置 Time.timeScale = 0;即可让游戏暂停。 其实我们暂停的主要是 人物动画,还有技能特效,比如一个火球打了一半。UI方面往往我们不希望暂停,比如暂停界面 有一些UI位移动画或者帧动画, 或者最起码要有个“取消暂停的按钮” 吧。 总不能游戏暂停了我点击按钮 按钮的点击动画 或者特效也暂停了吧。

    所有的动画都是基于时间来的,因为Time.timeScale = 0了,所以Time.time也就不会在变化了。换句话来说如果游戏暂停以后想在暂停界面上继续播放一些不受Time.timeScale 影响的动画,那么我们就需要用到Time.realtimeSinceStartup

    如果你的项目NGUI的版本还算比较新的话,你会发现在UITweener.cs处理UI动画的基类里面已经增加了一个属性叫public bool ignoreTimeScale = true; 它就是控制控制NGUI 的UI动画是否受到ignoreTimeScale影响。如下图所示,你可以看看NGUI在Update里面的实现,它也是根据时间来判断的。忽略timescale的话就用真实时间,不忽略的话就用Time.time 和Time.deltaTime。

    2.如何让游戏中某个游戏对象不受Time.timeScale影响。

    动画不受timeScale影响:

    http://answers.unity3d.com/questions/217351/animations-ignore-timescale.html

     1 1
     2 2
     3 3
     4 4
     5 5
     6 6
     7 7
     8 8
     9 9
    10 10
    11 11
    12 12
    13 13
    14 14
    15 15
    16 16
    17 17
    18 18
    19 19
    20 20
    21 21
    22 22
    23 23
    24 24
    25 25
    26 26
    27 27
    28 28
    29 29
    30 30
    31 31
    32 32
    33 33
    34 34
    35 35
    36 36
    37 37
    38 38
    39 39
    40 40
    41 41
    42 42
    43 43
    44 44
    45 45
    46 46
    47     static IEnumerator Play( Animation animation, string clipName, bool useTimeScale,System.Action onComplete )
    48     {
    49         if(!useTimeScale)
    50         {
    51             AnimationState _currState = animation[clipName];
    52             bool isPlaying = true;
    53             float _startTime = 0F;
    54             float _progressTime = 0F;
    55             float _timeAtLastFrame = 0F;
    56             float _timeAtCurrentFrame = 0F;
    57             float deltaTime = 0F;
    58             animation.Play(clipName);
    59             _timeAtLastFrame = Time.realtimeSinceStartup;
    60             while (isPlaying) 
    61             {
    62                 _timeAtCurrentFrame = Time.realtimeSinceStartup;
    63                 deltaTime = _timeAtCurrentFrame - _timeAtLastFrame;
    64                 _timeAtLastFrame = _timeAtCurrentFrame; 
    65                 
    66                 _progressTime += deltaTime;
    67                 _currState.normalizedTime = _progressTime / _currState.length; 
    68                 animation.Sample ();
    69                 if (_progressTime >= _currState.length) 
    70                 {
    71                     if(_currState.wrapMode != WrapMode.Loop)
    72                     {
    73                         isPlaying = false;
    74                     }
    75                     else
    76                     {
    77                         _progressTime = 0.0f;
    78                     }
    79                 }
    80                 yield return new WaitForEndOfFrame();
    81             }
    82             yield return null;
    83             if(onComplete != null)
    84             {
    85                 onComplete();
    86             } 
    87         }
    88         else
    89         {
    90             animation.Play(clipName);
    91         }
    92     }
    View Code

    粒子特效不受timescale影响

    https://gist.github.com/AlexTiTanium/5676482

     1 1
     2 2
     3 3
     4 4
     5 5
     6 6
     7 7
     8 8
     9 9
    10 10
    11 11
    12 12
    13 13
    14 14
    15 15
    16 16
    17 17
    18 18
    19 19
    20 20
    21 21
    22 22
    23 23
    24 24
    25 25
    26 26
    27 27
    28 28
    29 29
    30 30
    31 31
    32 using UnityEngine;
    33 using System.Collections;
    34  
    35 public class ParticaleAnimator : MonoBehaviour {
    36   
    37     private void Awake()
    38     {
    39         particle = GetComponent<ParticleSystem>();
    40     }
    41  
    42     // Use this for initialization
    43     void Start ()
    44     {
    45         lastTime = Time.realtimeSinceStartup;
    46     }
    47     
    48     // Update is called once per frame
    49     void Update () 
    50     {
    51         
    52         float deltaTime = Time.realtimeSinceStartup - (float)lastTime;
    53  
    54             particle.Simulate(deltaTime, true, false); //last must be false!!
    55  
    56             lastTime = Time.realtimeSinceStartup;
    57     }
    58  
    59     private double lastTime;
    60     private ParticleSystem particle;
    61  
    62 }
    View Code

    经过我的测试发现timeScale = 0 时, 播放放粒子特效,效率上有很大问题非常的卡。

    举个例子啊,刀塔传奇大家都玩过吧?某个角色放技能的时候,其他所有人物动作全部暂停,并且打出去的技能也暂停。等着角色的技能全部放完,别人才恢复正常。 我觉得向做这类游戏,最好就不要 利用timeScale了,不然写起来太蛋疼了。 不过刀塔传奇也没有 1 倍 2倍  3倍速 的功能吧,呵呵。

    3.timeScale变化时的声音。

    当声音播放的同时去修改timescale的数值你会发现声音播放的很奇怪。如下代码所示,你可以封装一个方法,把IgnoreTimeScale作为参数传进去, 如果忽略timescale的话那么速度就应该是1否则就应该是Time.timeScale。

    1 //添加一个声音组件
    2 AudioSource source = gameObject.AddComponent<AudioSource>();
    3 //设置播放声音的速度。 默认速度是1 ,那如果我们加速了,那就应该是 Time.timeScale
    4 source.pitch =IgnoreTimeScale?1:Time.timeScale;
    5 //播放声音
    6 source.Play();
    View Code

    此时如果修改了Time.timeScale的数值的话,那么正在播放中的声音会非常奇怪。所以当每次播放音频的时候我们需要记录一下这个音频的状态,它是否需要忽略timeScale当前的数值。

    1 //创建一个音频的字典
    2 private static Dictionary<AudioSource,bool>soundList = new Dictionary<AudioSource, bool>();
    3  
    4 //播放声音
    5 source.Play();
    6  
    7 //把音频对象加入字典中,value 就是是否忽略timescale
    8 soundList.Add(source,IgnoreTimeScale);
    View Code

    每当timeScale变化的时候调用一下下面这个方法。就是遍历一下当前保存的所有音频对象,从新设置一下他们的播放频率。

     1 public static void TimeScaleChanged()
     2     {
     3         foreach (AudioSource source in soundList.Keys)  
     4         {  
     5             if(source != null)
     6             {
     7                 source.pitch =    soundList[source]?1:Time.timeScale;
     8             }
     9         }  
    10     }
    View Code
  • 相关阅读:
    [转]VS2013自带SQL Server 的启用方法
    [转]CryptographyHelper.cs
    [转]Oracle 经验集
    程序的健壮性和鲁棒性
    死理性派恋爱法:拒绝掉前面37%的人
    Asp.net页面间传值方式汇总
    【操作系统】总结五(I/O管理)
    Windows编程
    【操作系统】磁盘
    【操作系统】文件系统
  • 原文地址:https://www.cnblogs.com/Peng18233754457/p/7798818.html
Copyright © 2011-2022 走看看