Time.timeScale变化后会影响谁?大多数的回答都是:“Time.timeScale可以控制Update 和LateUpdate 的执行速度,FixedUpdate还是按正常时间来执行。”
这就是理解错误了,一定要纠正一下错误的观点,正确的应该是:
1:“timeScale不会影响Update和LateUpdate的执行速度”
2:“FixedUpdate是根据时间来的,所以timeScale只会影响FixedUpdate的速度”
粉红色的回忆。。。
我写了一个例子,大家来看一下就明白了,由于排版问题,代码粘贴上来会乱,我就直接截图了。
Time.timeScale = 0 的话所有的Update都不执行了。今天测试了一下发现原来不是这样的,无论Time.timeScale 等于多说Update和LateUpdate都会去执行,不信你可以自己做个实验看看。
先解释下代码中Time.realtimeSinceStartup - _lastUpdateTime( _lastLateUpdateTime, _lastFixedUpdateTime)
就是获得真实的每次调用Update,LateUpdate,FixedUpdate方法的时间间隔,也可以用RealTime.deltaTime.
当TimeScaleParam = 1:
当TimeScaleParam = 5:
看前两个截图,我们发现timescale为1和5的时候,update,lateUpdate调用的时间间隔都是固定的,并不会对他们两个造成影响。然后我们又发现另外一个奇怪的现象,FixedUpdate被调用了5次,所以这就涉及到了另外一个问题了,看下面的截图:
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;
}