这个是由Flappy Bird引出来的问题,需求非常简单:
- 在一个固定位置定时创建一个管子
- 所有的管子均以一个固定速度向左移动
- 当管子到达某个位置后销毁。
根据王选易的教程,一开始用了协程的方法:
StartCoroutine(CreateTube(Holder));//开启协程 IEnumerator CreateTube(GameObject obj)//做一个迭代器 { //等待2秒 yield return new WaitForSeconds(2); //在一个固定位置定时创建一个管子 Rigidbody2D temp = Instantiate(Tube, new Vector2(5, 2), Quaternion.identity) as Rigidbody2D; //所有的管子均以一个固定速度向左移动 temp.velocity = new Vector2(-2, 0); //固定间隔时间开启协程 StartCoroutine(CreateTube(_holder)); //每帧轮询管子是否到达某个位置 while (temp.transform.position.x >= -6) { yield return null;//满足条件返回空 } //到达位置后销毁 Destroy(temp.gameObject); }
对于我这种新手来说,好复杂呀,关键还要每帧轮询,于是想到了:
//弄个2d刚体的集合 readonly List<Rigidbody2D> _tubeList = new List<Rigidbody2D>(); //3秒后开始执行,以后每2秒执行一次函数 InvokeRepeating("CreateTube01", 3, 2); void CreateTube01() { //在一个固定位置定时创建一个管子 Rigidbody2D temp = Instantiate(Tube, new Vector2(5, 2), Quaternion.identity) as Rigidbody2D; //所有的管子均以一个固定速度向左移动 temp.velocity = new Vector2(-2, 0); //入栈 _tubeList.Add(item: temp); //每2秒轮询一次管子是否到达某个位置 if (_tubeList[0].transform.position.x <= -6) { //到达位置后销毁 Destroy(_tubeList[0].gameObject); //出栈 _tubeList.RemoveAt(0); } }
还可以用Time类来实现:
- Time.time:从游戏开始后开始计时,表示截止目前共运行的游戏时间。
- Time.deltaTime:获取Update()方法中完成上一帧所消耗的时间。
- Time.fixedTime:FixedUpdate()方法中固定消耗的时间总和。FixedUpdate()每一帧更新的时间可以通过导航菜单栏”Edit“——”Project Settings“——”Time“菜单项去设置。
- Time.fixedDeltaTime:固定更新上一帧所消耗的时间。
对比两个方法:
协程可以传递参数,而InvokeRepeating不可以。
协程可以实现更复杂的逻辑,而InvokeRepeating就是定时执行函数
协程判断条件需要每帧轮询,而InvokeRepeating是定时轮询
InvokeRepeating的定时机制又是怎么实现的呢?猜想也是每帧轮询
IEnumerator MyWaitFunction(float delay) { float timer = Time.time + delay; while (Time.time < timer) { yield return null; } }
上面的猜想好像不对,再猜Invoke是u3d的委托机制,定时的机制为:
Thread.Sleep(1000)
新手教学!哈哈