在项目中一直使用Time.timeScale来加速整个游戏的1倍2倍,今天仔细看了Time.timeScale之后,才发现以前理解错了什么。
Time.timeScale可以控制Update和LateUpdate的执行速度。 举个例子来说明。
如果Time.timeScale=1,则Update、LateUpdate和FixedUpdate都将在正常时间运行。
如果Time.timeScale=2,则Update和LateUpdate的运行速度将是以前的两倍,但FixedUpdate将在正常时间运行。
Sorry上面的红色部分确实写错了。 感谢网友的评论。 谢谢你。
正确的是,timeScale不会影响Update和LateUpdate的执行速度。 “FixedUpdate”是基于时间的,因此“timeScale”只影响“FixedUpdate”的速度。 再次对不起。 谢谢热心网友的指正。 在我的项目中,处理战斗部分时会大量使用iTween,所以23倍加速和暂停的功能会直接修正timeScale。
Time.timeScale也误会了我很久。 为什么会这样呢? 我以为如果Time.timeScale=0,所有的Update都将不再运行。 今天测试了一下,结果不是那样的。 无论Time.timeScale怎么说Update和LateUpdate都等于执行。 信不信由你,你自己试着实验一下。
Time.timeScale也会影响Time.time的时间。 例如,如果Time.timeScale=2,则Time.time的增长速度也将加倍。 如果想留出游戏的实际时间,使用Time.timeSinceLevelLoad就可以了。 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的影响。 如下图所示,请看Update中的NGUI实现。 那个也由时间判断。 忽略timescale时使用实时,不忽略时使用Time.time和Time.deltaTime。
2 .如何使游戏中的某个游戏对象不受Time.timeScale的影响。
动画不受timeScale的影响:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
p>46
staticIEnumeratorPlay(Animationanimation,stringclipName,booluseTimeScale,System.ActiononComplete)
{
if(!useTimeScale)
{
AnimationState_currState=animation[clipName];
boolisPlaying=true;
float_startTime=0F;
float_progressTime=0F;
float_timeAtLastFrame=0F;
float_timeAtCurrentFrame=0F;
floatdeltaTime=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;
}
}
yieldreturnnewWaitForEndOfFrame();
}
yieldreturnnull;
if(onComplete!=null)
{
onComplete();
}
}
else
{
animation.Play(clipName);
}
}
粒子特效不受timescale影响
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
usingUnityEngine;
usingSystem.Collections;
publicclassParticaleAnimator:MonoBehaviour{
privatevoidAwake()
{
particle=GetComponent();
}
// Use this for initialization
voidStart()
{
lastTime=Time.realtimeSinceStartup;
}
// Update is called once per frame
voidUpdate()
{
floatdeltaTime=Time.realtimeSinceStartup-(float)lastTime;
particle.Simulate(deltaTime,true,false);//last must be false!!
lastTime=Time.realtimeSinceStartup;
}
privatedoublelastTime;
privateParticleSystemparticle;
}
经过我的测试发现timeScale = 0 时, 播放放粒子特效,效率上有很大问题非常的卡。
举个例子啊,刀塔传奇大家都玩过吧?某个角色放技能的时候,其他所有人物动作全部暂停,并且打出去的技能也暂停。等着角色的技能全部放完,别人才恢复正常。 我觉得向做这类游戏,最好就不要 利用timeScale了,不然写起来太蛋疼了。 不过刀塔传奇也没有 1 倍 2倍 3倍速 的功能吧,呵呵。
3.timeScale变化时的声音。
当声音播放的同时去修改timescale的数值你会发现声音播放的很奇怪。如下代码所示,你可以封装一个方法,把IgnoreTimeScale作为参数传进去, 如果忽略timescale的话那么速度就应该是1否则就应该是Time.timeScale。
1
2
3
4
5
6
//添加一个声音组件
AudioSourcesource=gameObject.AddComponent();
//设置播放声音的速度。 默认速度是1 ,那如果我们加速了,那就应该是 Time.timeScale
source.pitch=IgnoreTimeScale?1:Time.timeScale;
//播放声音
source.Play();
此时如果修改了Time.timeScale的数值的话,那么正在播放中的声音会非常奇怪。所以当每次播放音频的时候我们需要记录一下这个音频的状态,它是否需要忽略timeScale当前的数值。
1
2
3
4
5
6
7
8
//创建一个音频的字典
privatestaticDictionarysoundList=newDictionary();
//播放声音
source.Play();
//把音频对象加入字典中,value 就是是否忽略timescale
soundList.Add(source,IgnoreTimeScale);
每当timeScale变化的时候调用一下下面这个方法。就是遍历一下当前保存的所有音频对象,从新设置一下他们的播放频率。
1
2
3
4
5
6
7
8
9
10
publicstaticvoidTimeScaleChanged()
{
foreach(AudioSourcesourceinsoundList.Keys)
{
if(source!=null)
{
source.pitch=soundList[source]?1:Time.timeScale;
}
}
}
如果你有更好的建议,欢迎在下面给我留言,谢谢。
最后编辑:2016-05-03作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!