unity开发游戏的unity 倒计时功能能怎么实现

项目---小功能(3)
感慨下,想法是容易的做也是容易的。难的是坚持,贵在坚持吧。突然发现好一段时间没写了。
项目中遇到的问题
网络游戏一般到有倒计时功能,无论是否修改时间都不会导致倒计时混乱。
using UnityE
using System.C
public class SyncTime : MonoBehaviour
public static DateTime UtcNow { get { return DateTime.UtcNow.AddSeconds(DeltaTime); } }
//public static DateTime Now { get { return DateTime.Now.AddSeconds(DeltaTime); } }
private static double DeltaTime = 0;
private static double ServerTime = 0;
private static double ValidStartGameTime = 0;
//同步服务器时间
public static void Sync(long time)
ValidStartGameTime = Time.realtimeSinceS
DateTime dt = new DateTime(, 0, 0, 0, DateTimeKind.Unspecified).AddSeconds(time);
DeltaTime = (dt - DateTime.UtcNow).TotalS
ServerTime =
//剩余时间
public static TimeSpan GetLeftTime(long validTime)
TimeSpan ts = (new DateTime().AddSeconds((double)validTime)).Subtract(SyncTime.UtcNow);
//当前服务器时间
public static DateTime GetSystemTime()
DateTime dateTime = (new DateTime().AddSeconds((double)ServerTime)).AddSeconds((double)(Time.realtimeSinceStartup - ValidStartGameTime));
return dateT
调用例子:登陆游戏成功同步服务器时间。然后调用GetSystemTime(validTime 是指某一个具体某一个点的时间)就可以了
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:7923次
排名:千里之外
(1)(1)(1)(1)(3)当前位置: >
unity中时间的用法:Time.timeScale、游戏暂停
时间: 22:14 来源:互联网 作者:网络 浏览:
项目里面一直在用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 = 它就是控制控制NGUI 的UI动画是否受到ignoreTimeScale影响。如下图所示,你可以看看NGUI在Update里面的实现,它也是根据时间来判断的。忽略timescale的话就用真实时间,不忽略的话就用Time.time 和Time.deltaTime。2.如何让游戏中某个游戏对象不受Time.timeScale影响。动画不受timeScale影响:/questions/217351/animations-ignore-timescale.html&&&&static&IEnumerator&Play(&Animation&animation,&string&clipName,&bool&useTimeScale,System.Action&onComplete&)
if(!useTimeScale)
AnimationState&_currState&=&animation[clipName];
bool&isPlaying&=&
float&_startTime&=&0F;
float&_progressTime&=&0F;
float&_timeAtLastFrame&=&0F;
float&_timeAtCurrentFrame&=&0F;
float&deltaTime&=&0F;
animation.Play(clipName);
_timeAtLastFrame&=&Time.realtimeSinceS
while&(isPlaying)
_timeAtCurrentFrame&=&Time.realtimeSinceS
deltaTime&=&_timeAtCurrentFrame&-&_timeAtLastF
_timeAtLastFrame&=&_timeAtCurrentF
_progressTime&+=&deltaT
_currState.normalizedTime&=&_progressTime&/&_currState.
animation.Sample&();
if&(_progressTime&&=&_currState.length)
if(_currState.wrapMode&!=&WrapMode.Loop)
isPlaying&=&
_progressTime&=&0.0f;
yield&return&new&WaitForEndOfFrame();
yield&return&
if(onComplete&!=&null)
onComplete();
animation.Play(clipName);
}粒子特效不受timescale影响/AlexTiTanium/5676482using&UnityE
using&System.C
publicclassParticaleAnimator:MonoBehaviour{
privatevoidAwake()
particle=GetComponent&ParticleSystem&();
//&Use&this&for&initialization
voidStart()
lastTime=Time.realtimeSinceS
//&Update&is&called&once&per&frame
voidUpdate()
floatdeltaTime=Time.realtimeSinceStartup-(float)lastT
particle.Simulate(deltaTime,true,false);//last&must&be&false!!
lastTime=Time.realtimeSinceS
privatedoublelastT
privateParticleSystem&
}经过我的测试发现timeScale = 0 时, 播放放粒子特效,效率上有很大问题非常的卡。举个例子啊,刀塔传奇大家都玩过吧?某个角色放技能的时候,其他所有人物动作全部暂停,并且打出去的技能也暂停。等着角色的技能全部放完,别人才恢复正常。 我觉得向做这类游戏,最好就不要 利用timeScale了,不然写起来太蛋疼了。 不过刀塔传奇也没有 1 倍 2倍& 3倍速 的功能吧,呵呵。3.timeScale变化时的声音。当声音播放的同时去修改timescale的数值你会发现声音播放的很奇怪。如下代码所示,你可以封装一个方法,把IgnoreTimeScale作为参数传进去, 如果忽略timescale的话那么速度就应该是1否则就应该是Time.timeScale。//添加一个声音组件
AudioSource&source=gameObject.AddComponent&AudioSource&();
//设置播放声音的速度。&默认速度是1&,那如果我们加速了,那就应该是&Time.timeScale
source.pitch=IgnoreTimeScale?1:Time.timeS
//播放声音
source.Play();此时如果修改了Time.timeScale的数值的话,那么正在播放中的声音会非常奇怪。所以当每次播放音频的时候我们需要记录一下这个音频的状态,它是否需要忽略timeScale当前的数值。//创建一个音频的字典
privatestaticDictionary&AudioSource,bool&soundList=newDictionary&AudioSource,bool&();
//播放声音
source.Play();
//把音频对象加入字典中,value&就是是否忽略timescale
soundList.Add(source,IgnoreTimeScale);每当timeScale变化的时候调用一下下面这个方法。就是遍历一下当前保存的所有音频对象,从新设置一下他们的播放频率。publicstaticvoidTimeScaleChanged(){
foreach(AudioSource&source&insoundList.Keys)
if(source!=null)
source.pitch=soundList[source]?1:Time.timeS
}如果你有更好的建议,欢迎在下面给我留言,谢谢。
(责任编辑:脚印)
免责声明:Unity之家部分内容来源于互联网,如有侵权,请联系我们,本站将立即进行处理。
猜你也喜欢看这些 ??????
其他类型的Unity入门 ??????Unity3D中的工具类-Time类 - stephen830 - ITeye技术网站
博客分类:
Unity3D中的工具类-Time类
1、时间:Unity提供了Time类,这个类主要用来获取当前的系统时间。 Time.time:从游戏开始后开始计时,表示截止目前共运行的游戏时间。 Time.deltaTime:获取Update()方法中完成上一帧所消耗的时间。 Time.fixedTime:FixedUpdate()方法中固定消耗的时间总和。FixedUpdate()每一帧更新的时间可以通过导航菜单栏”Edit“——”Project Settings“——”Time“菜单项去设置。 Time.fixedDeltaTime:固定更新上一帧所消耗的时间。2、等待:在程序中使用WaitForSeconds()方法可以以秒为单位让程序等待一段时间,此方法可直接使游戏主线程进入等待状态。
3、随机数:在开发中,有时需要获取程序中的随机数,这可以使用Random.Range()方法实现,其中该方法的第一个参数为随机数的起始位置,第二个参数为获取的随机数的结束位置。
4、数学:Unity开发中封装了一个数学类Mathf,使用它可以很轻松地帮我们解决复杂的数学公式。
5、四元数:四元数是非常重要的工具类之一。在Unity中所有用到模型旋转的,其底层都是有四元数实现的,它可以精确地计算模型旋转的角度。
浏览 12726
stephen830
浏览: 1722156 次
来自: 上海
非常感谢,正好用上
提示的/222.177.4.242
无法链接到ip地址,是什 ...Unity时钟定时器插件——Vision Timer源码分析之一 - One thing I know,that is I know nothing.(Socrates Greek)
- ITeye技术网站
博客分类:
Unity时钟定时器插件——Vision Timer源码分析之一
By D.S.Qiu
尊重他人的劳动,支持原创,转载请注明出处:http.
因为项目中,UI的所有模块都没有MonBehaviour类(纯粹的C#类),只有像NGUI的基本组件的类是继承MonoBehaviour。因为没有继承MonoBehaviour,这也不能使用Update,InVoke,StartCoroutine等方法,这样就会显得很蹩脚。后来一个同事添加vp_Timer和vp_TimeUtility这两个类。后来研究了下vp_Timer至少可以弥补没有Update,InVoke,InVokeRepeat的不足。
之前用的时候,就粗略的研究过vp_Timer这个类,一直就想仔细剖析下,但是由于不仅工作任务中,自己也有很多要琐碎的事情,我都很久自己好好学习了,虽然还有一堆事情要做,但是憋了太久了,先满足下自己,所以才有开始认真分析vp_Timer的代码并才有这篇博客。
vp_Timer 一共有3个class,都各司其职:vp_Timer,Event,Handle
1)vp_Timer:提供的使用接口,通过静态方法vp_Timer.In(),加入定时器事件(函数,这里将传入的函数称为事件)
2)Event:用来封装传入的事件(函数),保持事件的状态
3)Handle:对事件状态提供查询接口(事件执行了多长时间,结束时间,是否还是Active)以及提供 Excute(立即执行事件),Cancel(取消事件),Pause(暂停事件)等操作
很容易就可以理清这三者的关系,通过vp_Timer.In方法将传入的事件(函数)封装为Event对象,然后返回(虽然是通过参数)Handle对象让调用者可以查询事件的状态和进行相关操作。
先看下vp_Timer的成员变量(c#应该称为filed)
GameObject m_MainObject:vp_Timer是一个MonoBehaviour,就一定要挂载GameObject上,m_MainObject会在第一次调用vp_Timer.In方法时创建:
// setup main gameobject
if (m_MainObject == null)
m_MainObject = new GameObject("Timers");
m_MainObject.AddComponent&vp_Timer&();
UnityEngine.Object.DontDestroyOnLoad(m_MainObject);
#if (UNITY_EDITOR && !DEBUG)
m_MainObject.gameObject.hideFlags = HideFlags.HideInH
List&Event& m_Active 和 List&Event& m_Pool :这个List都是Event的缓存,其中,m_Active缓存Active的Event,m_Pool缓存无效的Event,这里的Acitive是事件仍然需要执行,无效说明不会再被调用。之所有要缓存无效的Event,是为了节省创建Event对象的消耗。m_Pool就好比垃圾箱,m_Active是一个成品工厂,每次m_Active要生产(Add)新的Event,都去m_Pool取没用的原料(Event),当m_Active的成品没用了,用放会m_Pool中去,这样就达到了循环利用作用。
Event m_NewEvent :在Schedule方法里使用的变量,其实完全可以声明为Schedule的局部变量,为了节省重复创建和销毁的消耗,vp_Timer就声明一个成员变量。
private static int m_EventCount = 0;
// variables for the Update method
int m_EventBatch 和int m_EventIterator:在Update使用的变量,m_EventBatch记录在一次Update中执行事件的次数,m_EventIterator记录是每次执行事件在m_Active的索引。
int MaxEventsPerFrame :一次循环(Update)执行事件最大次数
假设MaxEventPerFarme = 10 , m_Active.Count = 5,那么每次Update都会遍历2次m_Active的Event,看是否可以执行(调用Excute函数)。这样就可以理解这三个参数的具体含义了。
private class Event
public int Id;
//标记Event,如果Id = 0 ,表示该Event已经无效,就被Add进m_Pool中,Handle对象和Evnt就是通过Id来关联的
public Callback Function =
//函数委托 Callback和ArgCallback是vp.Timer定义的函数委托(原型)
public ArgCallback ArgFunction =
public object Arguments =
public int Iterations = 1;
//事件的迭代(执行次数)
public float Interval = -1.0f;
//执行时间间隔
public float DueTime = 0.0f;
//下一个事件执行的时间 DueTime = Time.time + Time.deltaTime
public float StartTime = 0.0f;
//事件开始执行事件 StartTime = Time.Time + delayTime
public float LifeTime = 0.0f;
//事件累积的总时间 LifeTime += Time.deltaTime
public bool Paused =
#if (DEBUG && UNITY_EDITOR)
private string m_CallingMethod = "";
//省略其他代码
当然还有几个方法:
Excute():执行Function和ArgFunction
private void Recycle()
DueTime = 0.0f;
StartTime = 0.0f;
Function =
ArgFunction =
Arguments =
if (vp_Timer.m_Active.Remove(this))
//从m_Active进入m_Pool
m_Pool.Add(this);
#if (UNITY_EDITOR && DEBUG)
EditorRefresh();
MethodName:由于D.S.Qiu对delegate还没有深入研究理解,目前还说不清如何比较两个委托是否相等,但是得到一个经验就是不能用 函数 来比较,所以看到很多插件(最典型的就是Unity的StopCoroutine只有字符串作为参数和NGUI的EventDelegate)都使用的字符串来标记delegate,看下面的代码:
public string MethodName
if (Function != null)
if (Function.Method != null)
if (Function.Method.Name[0] == '&')
return "delegate";
else return Function.Method.N
else if (ArgFunction != null)
if (ArgFunction.Method != null)
if (ArgFunction.Method.Name[0] == '&')
return "delegate";
else return ArgFunction.Method.N
这样vp_Timer才有Cancel(string methodName)的方法:
public static void CancelAll(string methodName)
for (int t = vp_Timer.m_Active.Count - 1; t & -1; t--)
if (vp_Timer.m_Active[t].MethodName == methodName)
vp_Timer.m_Active[t].Id = 0;
前面介绍过,Handle是用来查询和操作Event的对象,Handle对象和Event桶Id关联起来。
public int Id
return m_Id;
if (m_Id == 0)
m_Event.DueTime = 0.0f;
for (int t = vp_Timer.m_Active.Count - 1; t & -1; t--)
if (vp_Timer.m_Active[t].Id == m_Id)
m_Event = vp_Timer.m_Active[t];
if (m_Event == null)
UnityEngine.Debug.LogError("Error: (vp_Timer.Handle) Failed to assign event with Id '" + m_Id + "'.");
// store some initial event info
m_StartIterations = m_Event.I
m_FirstDueTime = m_Event.DueT
还说vp_Timer:
前面介绍了vp_Timer的成员变量以及Event和Handle,就差vp_Timer的使用了,通过调用vp_Timer.In函数将事件加入vp_Timer的mActive队列:
// time + callback + [timer handle]
public static void In(float delay, Callback callback, Handle timerHandle = null)
{ Schedule(delay, callback, null, null, timerHandle, 1, -1.0f); }
// time + callback + iterations + [timer handle]
public static void In(float delay, Callback callback, int iterations, Handle timerHandle = null)
{ Schedule(delay, callback, null, null, timerHandle, iterations, -1.0f); }
// time + callback + iterations + interval + [timer handle]
public static void In(float delay, Callback callback, int iterations, float interval, Handle timerHandle = null)
{ Schedule(delay, callback, null, null, timerHandle, iterations, interval); }
// time + callback + arguments + [timer handle]
public static void In(float delay, ArgCallback callback, object arguments, Handle timerHandle = null)
{ Schedule(delay, null, callback, arguments, timerHandle, 1, -1.0f); }
// time + callback + arguments + iterations + [timer handle]
public static void In(float delay, ArgCallback callback, object arguments, int iterations, Handle timerHandle = null)
{ Schedule(delay, null, callback, arguments, timerHandle, iterations, -1.0f); }
// time + callback + arguments + iterations + interval + [timer handle]
public static void In(float delay, ArgCallback callback, object arguments, int iterations, float interval, Handle timerHandle = null)
{ Schedule(delay, null, callback, arguments, timerHandle, iterations, interval); }
看到都是对Schedule的封装:
private static void Schedule(float time, Callback func, ArgCallback argFunc, object args, Handle timerHandle, int iterations, float interval)
if (func == null && argFunc == null)
UnityEngine.Debug.LogError("Error: (vp_Timer) Aborted event because function is null.");
// setup main gameobject
if (m_MainObject == null)
//new 一个 m_MainObject,挂载vp_Timer_
m_MainObject = new GameObject("Timers");
m_MainObject.AddComponent&vp_Timer&();
UnityEngine.Object.DontDestroyOnLoad(m_MainObject);
#if (UNITY_EDITOR && !DEBUG)
m_MainObject.gameObject.hideFlags = HideFlags.HideInH
// force healthy time values
time = Mathf.Max(0.0f, time);
iterations = Mathf.Max(0, iterations);
interval = (interval == -1.0f) ? time : Mathf.Max(0.0f, interval);
// recycle an event - or create a new one if the pool is empty:先从m_Pool中去Event,如果m_Pool为空则直接new一个
m_NewEvent =
if (m_Pool.Count & 0)
m_NewEvent = m_Pool[0];
m_Pool.Remove(m_NewEvent);
m_NewEvent = new Event();
// iterate the event counter and store the id for this event
vp_Timer.m_EventCount++;
m_NewEvent.Id = vp_Timer.m_EventC
//Event的Id为当前队列的总数
// set up the event with its function, arguments and times
if (func != null)
m_NewEvent.Function =
else if (argFunc != null)
m_NewEvent.ArgFunction = argF
m_NewEvent.Arguments =
m_NewEvent.StartTime = Time.
//设置Event的成员变量
m_NewEvent.DueTime = Time.time +
m_NewEvent.Iterations =
m_NewEvent.Interval =
m_NewEvent.LifeTime = 0.0f;
m_NewEvent.Paused =
// add event to the Active list
vp_Timer.m_Active.Add(m_NewEvent);
// if a timer handle was provided, associate it to this event,
// but first cancel any already active event using the same
// handle: there can be only one ...
if (timerHandle != null)
if (timerHandle.Active)
timerHandle.Cancel();
// setting the 'Id' property associates this handle with
// the currently active event with the corresponding id
timerHandle.Id = m_NewEvent.Id;
//关联Handle和Event,然后Handle就可以通过关联的Event查询其状态和操作
Update:通过比对Time.time和Event.DueTime,如果Time.time &= Event.DueTime 则执行Event的Excute方法。
private void Update()
// NOTE: this method never processes more than 'MaxEventsPerFrame',
// in order to avoid performance problems with excessive amounts of
// timers. this may lead to events being delayed a few frames.
// if experiencing delayed events 1) try to cut back on the amount
// of timers created simultaneously, and 2) increase 'MaxEventsPerFrame'
// execute any active events that are due, but only check
// up to max events per frame for performance
m_EventBatch = 0;
while ((vp_Timer.m_Active.Count & 0) && m_EventBatch & MaxEventsPerFrame)
// if we reached beginning of list, halt until next frame
if (m_EventIterator & 0)
// this has two purposes: 1) preventing multiple iterations
// per frame if our event count is below the maximum, and
// 2) preventing reaching index -1
m_EventIterator = vp_Timer.m_Active.Count - 1;
// prevent index out of bounds
if (m_EventIterator & vp_Timer.m_Active.Count - 1)
m_EventIterator = vp_Timer.m_Active.Count - 1;
// execute all due events
if (Time.time &= vp_Timer.m_Active[m_EventIterator].DueTime || // time is up
vp_Timer.m_Active[m_EventIterator].Id == 0)
// event has been canceled ('Execute' will kill it)
vp_Timer.m_Active[m_EventIterator].Execute();
// handle pausing
if (vp_Timer.m_Active[m_EventIterator].Paused)
vp_Timer.m_Active[m_EventIterator].DueTime += Time.deltaT
// log lifetime
vp_Timer.m_Active[m_EventIterator].LifeTime += Time.deltaT
// going backwards since 'Execute' will remove items from the list
m_EventIterator--;
m_EventBatch++;
差不多就这样了,很久没写博客了,感觉一点也不顺畅,虽然理解的很透彻,还是很为自己的写作功底捉急。
D.S.Qiu觉得在项目中很有必要有“管理”的思想,很多功能都是用一个类实现的,其他人只要调用就可以了,具体的逻辑只需要在一个类内部维护,可以做的统一控制,可以做到更自如,就拿vp_Timer和MonoBehaviour的InVokeRepeat方法来对比就有明显的优势:
1)vp_Timer可以随时查询事件的状态(事件被执行了次数等)还可以暂停事件,而InVokeRepeat做不到的
2)vp_Timer可以设置时间delatTime受不受Time.timeScale影响,而InVokeRepeat是没有这个参数设置的
3)vp_Timer可以对事件进行统一的管理,如果暂停所有事件的执行,这个点当Time.timeScale = 0 时特别管用,而InVokeRepeat是分散的,没有统一管理其他。
这有点“一夫当万夫莫开”的感觉。
不管是InVokeRepeat方法,MonoBehaviour的很多方法都有类似的缺陷,因为每一个MonoBehaviour都可以调用这些方法,就不能统一起来管理了,所以如果Unity当初能写一个专门的类我想会方便很多。
虽然觉得vp_Timer用的很爽,但是D.S.Qiu还是觉得有很多可以改进的地方:
1)vp_Timer提供Pause(string methodName)和PauseAll()的方法,从“管理”的角度上就更加完美了,当然还有对应的Play方法。
2)当Event的参数: Iterations 和
Interval 没有很好处理 Interval 和 Time.deltaTime 的具体情况,假设我们的 Iterations =100 , interval = 0.01f
即我需要达到1s内执行100次的目的,但按照vp_Timer的实现结果是执行了100次,但是时间一定是&= 1s,即当Time.deltaTime & interval 时,还是只执行一次,例如 Time.deltaTime = 0.02f, 理论上我们希望能执行两次,但是却只执行了一次。
3)vp_Timer要是提供 string methodName 到 Event 或 Handle 的查询接口就更加完美了。
4)vp_Timer虽然用了很多设计,对象的重复利用避免 new 和销毁对象的系统开销,但是专门用Handle专门管理Event,Handle的的功能只是对Event的一个封装,其实完全没有必要,完全可以让Event自己充当Handle的角色,直接返回Event对象会更直观,只有在回调的时候用参数返回关联的对象,要不然采用直接返回会更明白。
虽然上面的分析文章写得比较零乱,但是小结部分我还是很满意的,至少D.S.Qiu之前从来没有在这部分写那么多,算是分享自己的一些经验和体会吧,也发现自己对delegate的不足,又到1:30了时间真是不够用,4个小时就这么过去了。
如果您对D.S.Qiu有任何建议或意见可以在文章后面评论,或者发邮件(gd.s.)交流,您的鼓励和支持是我前进的动力,希望能有更多更好的分享。
转载请在文首注明出处:
更多精彩请关注D.S.Qiu的和微博(ID:静水逐风)
(486.4 KB)
下载次数: 138
浏览: 799354 次
来自: 广州
浏览量:141559
[quo[color=red]te][/color]
博主,你好,一直都有个问题没有搞明白,就是 2.x的版本是通过 ...
感谢楼主!
感谢!从你的博客里学到了很多
学习了~,话说现在的版本custom还真的变委托了}

我要回帖

更多关于 unity实现退出功能 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信