这个是由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)


新手教学!哈哈