Unity关于Time.timeScale详解

Time.timeScale变化后会影响谁?大多数的回答都是:“Time.timeScale可以控制Update 和LateUpdate 的执行速度,FixedUpdate还是按正常时间来执行。”

这就是理解错误了,一定要纠正一下错误的观点,正确的应该是:

1:“timeScale不会影响Update和LateUpdate的执行速度

2:“FixedUpdate是根据时间来的,所以timeScale只会影响FixedUpdate的速度

粉红色的回忆。。。

我写了一个例子,大家来看一下就明白了,由于排版问题,代码粘贴上来会乱,我就直接截图了。

Time.timeScale = 0 的话所有的Update都不执行了。今天测试了一下发现原来不是这样的,无论Time.timeScale 等于多说Update和LateUpdate都会去执行,不信你可以自己做个实验看看。

Unity关于Time.timeScale详解_第1张图片

先解释下代码中Time.realtimeSinceStartup - _lastUpdateTime( _lastLateUpdateTime, _lastFixedUpdateTime)

就是获得真实的每次调用Update,LateUpdate,FixedUpdate方法的时间间隔,也可以用RealTime.deltaTime.


当TimeScaleParam = 1:



当TimeScaleParam = 5:

Unity关于Time.timeScale详解_第2张图片

看前两个截图,我们发现timescale为1和5的时候,update,lateUpdate调用的时间间隔都是固定的,并不会对他们两个造成影响。然后我们又发现另外一个奇怪的现象,FixedUpdate被调用了5次,所以这就涉及到了另外一个问题了,看下面的截图:

Unity关于Time.timeScale详解_第3张图片
FixedUpdate被调用的时间也是不受timescale影响的,只跟我们在playerSetting里面设置的fixedTimestep有关系,那为什么跑了5次呢?因为timescale=5,时间被拉长,在这么长的时间里FixedUpdate按照fixedTimestep来计算总共跑了5次,所以也可以说FixedUpdate是受到timescale影响的。


当TimeScaleParam = 0:


这时候发现fixedUpdate没有了。。。。。


Time.timeScale会影响Time.time的时间,比如Time.timeScale = 2的话,那么Time.time的增长速度也会变成2倍速度。如果你想取到游戏的实际时间,按照我上面的例子来做就可以了。

总之一句话Time.timeScale影响的是Unity的游戏时间缩放比例。Unity里面所有跟时间有关系的东西都是根据timeScale来演算的。仔细想想现在的手游就是个 动画 和 粒子技能特效 还有UI位移特效,所以改他们的速度直接用Time.timeScale就可以完成。

我们如果想暂停游戏的话,Time.timeScale = 0 可以暂停游戏,Time.timeScale = 1 恢复正常,但这是作用于整个游戏的设置,不单单是当前场景,记得在需要的时候重置回Time.timeScale = 1。当然也可以使用Time.timeScale来做游戏的1倍、2倍整体加速。

我们不能仅仅去记这句话,游戏暂停的都是和所有和帧率无关的事情。这些主要是指所有的物理事件和依赖时间的函数、刚体力和速度等,而且FixedUpdate会受到影响,会被暂停(不是Update),即timeScale =0 时将不会调用FixedUpdate函数了。

那有人又会问了,Update和LateUpdate不是不受影响吗?那怎么就暂停游戏了呢?Update和LateUpdate并没有停,依然在渲染,只是你的代码中依赖于Time.deltaTime的逻辑将会被停掉了,因为Time.deltaTime = 0了。所以游戏看起来是被冻结了。

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


动画不受timeScale影响:

static IEnumerator Play( Animation animation, string clipName, bool useTimeScale,System.Action onComplete )

{

if(!useTimeScale)

{

AnimationState _currState = animation[clipName];

bool isPlaying = true;

float _startTime = 0F;

float _progressTime = 0F;

float _timeAtLastFrame = 0F;

float _timeAtCurrentFrame = 0F;

float deltaTime = 0F;

animation.Play(clipName);

_timeAtLastFrame = Time.realtimeSinceStartup;

while (isPlaying)

{

_timeAtCurrentFrame = Time.realtimeSinceStartup;

deltaTime = _timeAtCurrentFrame - _timeAtLastFrame;

_timeAtLastFrame = _timeAtCurrentFrame;

_progressTime += deltaTime;

_currState.normalizedTime = _progressTime / _currState.length;

animation.Sample ();

if (_progressTime >= _currState.length)

{

if(_currState.wrapMode != WrapMode.Loop)

{

isPlaying = false;

}

else

{

_progressTime = 0.0f;

}

}

yield return new WaitForEndOfFrame();

}

yield return null;

if(onComplete != null)

{

onComplete();

}

}

else

{

animation.Play(clipName);

}

}


粒子特效不受timescale影响

using UnityEngine;

using System.Collections;

public class ParticaleAnimator : MonoBehaviour {

private void Awake()

{

particle = GetComponent();

}

// Use this for initialization

void Start ()

{

lastTime = Time.realtimeSinceStartup;

}

// Update is called once per frame

void Update ()

{

float deltaTime = Time.realtimeSinceStartup - (float)lastTime;

particle.Simulate(deltaTime, true, false); //last must be false!!

lastTime = Time.realtimeSinceStartup;

}

private double lastTime;

private ParticleSystem particle;

}

你可能感兴趣的:(Unity)