赞
踩
Invoke 调用的函数不能带参数
Invoke(“printCount”, 2); 表示经过2秒钟之后调用printCount函数
InvokeRepeating(“printCount”, 3, 1); 经过3秒钟之后调用printCount函数,之后每隔1秒调用一次该函数
IsInvoking() 判断是否有通过Invoke方式调用的函数
CancelInvoke(); 取消这个脚本上所有的调用
CancelInvoke(string methodName); 取消名字为methodName的调用
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 一旦通过invoke启动了一个函数,该游戏对象是否激活失活无关,该组件是否有效无关 /// 该脚本一旦删除,其上所有invoke启动的函数都会取消执行 /// </summary> public class Invoke : MonoBehaviour { static int num; private void Awake() { print("Awake"); } void Start() { //直接调用函数 printCount(); //Invoke调用的函数不能带参数 Invoke("printCount", 2);//经过2秒钟之后调用printCount函数 InvokeRepeating("printCount", 3, 1);//经过3秒钟之后调用printCount函数,之后每隔1秒调用一次该函数 //Invoke("hasInvoke", 5); } // Update is called once per frame void Update() { } /// <summary> /// 注意:该函数不能有参数,如果有参数,异步调用执行不到该函数,不报错 /// </summary> void hasInvoke() { //判断是否有通过Invoke方式调用的函数 if (IsInvoking()) { CancelInvoke(); } } void printCount() { num++; print("num="+num); } }
1
Coroutine StartCoroutine(IEnumerator routine)
开启一个协程,利用yield语句暂停在某点,yield返回值指定了什么时机协程恢复。对于多帧执行一次的行为非常适合用协程解决,它几乎没有什么性能开销。参数传递没有限制。
2、
Coroutine StartCoroutine(string methodName, object value = null)
通过字符串开启一个协程,主要的目的是可以使用StopCoroutine来终止指定名字的函数,但是此种方法只能传递一个参数,性能上也有所损耗。
如下协程的启动方式
//形式一
StartCoroutine(CustomCorutineFn));
StartCoroutine(CustomCorutineFn(7));//向方法中传递参数
//形式二
StartCoroutine("CustomCorutineFn” );
StartCoroutine("CustomCorutineFn”,7);//向方法中传递参数
3
终止协议
1、void StopAllCoroutines()
终止运行在该MonoBehaviour上的所有协程。
2、void StopCoroutine(string methodName)
终止运行在该MonoBehaviour上的所有名字为methodName的协程。仅仅使用字符串开启的协程才可以使用该函数进行终止。
yield
yield是一种特殊类型的返回值语句,它可以确保函数在下一次被执行时,不是从头开始,而是从yield语句处开始,如果在函数中用了yield语句,需要把函数的返回值改成IEnumerator。yield后面可以有的表达式。
1、yield null(协程将在下一帧所有脚本的Update执行之后,再继续执行)
2、yield WaitForSeconds(协程在延迟指定时间,且当前帧所有脚本的Update全都执行结束后才继续执行)
3、WaitForEndOfFrame (一帧结束时,渲染之前)
4、yield WaitForFixedUpdate(协程在所有脚本的FixedUpdate执行之后,再继续执行,即等待物理更新时间0.02秒)
5.yield StartCoroutine(协程在指定协程执行结束后,再继续执行)6、yield wWW((协程在WWW下载资源完成后,再继续执行)
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 如果协程启动之后,该脚本所在的游戏对象失活状态,该游戏对象上所有的协程停止,游戏对象激活也不会执行其上的协程 /// 跟该脚本组件是否有效无关 /// 该脚本一旦删除,其上所有StartCoroutine启动的协程都会取消执行 /// </summary> public class Coroutine : MonoBehaviour { public GameObject prefab; // Start is called before the first frame update void Start() { //普通函数调用方式 //funCoroutine(3); //第一种:通过传入协程函数执行协程,这种方式不受参数的限制,不能制定该协程停止,只能通过StopAllCoroutines停止所有的协程 //StartCoroutine(funCoroutine(3)); //第二种:通过传入协程函数名字执行协程,注意,如果有参数而传递,该协程函数启动不了,而且报错, //这种启动方式可以通过StopCoroutine停止该协程函数 //如果函数有参数,只能一个参数 StartCoroutine("funCoroutine",3); StartCoroutine(createGameObject(1)); } // Update is called once per frame void Update() { if(IsInvoking()) { print("IsInvoking"); } } /// <summary> /// 定义协程函数 /// 返回值:IEnumerator /// 函数体:一定要有yield return语句 /// </summary> /// <param name="time"></param> /// <returns></returns> IEnumerator funCoroutine(float waitTime) { print("start funCoroutine " + Time.time+" frameCount="+Time.frameCount); yield return null;//挂起协程,挂起一帧,等待时间到了之后继续执行下面的代码 print("yield return null "+Time.time + " frameCount=" + Time.frameCount); yield return 100;//挂起一帧 print("yield return 100 " + Time.time + " frameCount=" + Time.frameCount); yield return 100;//挂起一帧 print("yield return 100 " + Time.time + " frameCount=" + Time.frameCount); yield return new WaitForSeconds(waitTime);//挂起指定时间,秒 print("yield return new WaitForSeconds + waitTime " + +Time.time + " frameCount=" + Time.frameCount); yield return 1000000;//挂起一帧 print("yield return 1000000 " + Time.time + " frameCount=" + Time.frameCount); } IEnumerator createGameObject(float dtTime) { while (true) { GameObject go= Instantiate<GameObject>(prefab); go.SetActive(true); go.transform.parent = transform; yield return new WaitForSeconds(dtTime); if(transform.childCount>=20) { StopAllCoroutines(); } } } }
1.在X正方向上有5个物体,依次排列开,实现从第一个物体上升到5米高时第二个物体开始上升,依次执行到最后一个物体。
思路:
协程来控制是哪一个球向上移动,分别替换go游戏对象,等待五秒换下一个, 因为设置的速度是1m/s 所以正常来说5m左右就会停下,但也会有些许的误差,因为每帧的时间都不可能完全一样。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Spheres : MonoBehaviour { GameObject go; int index; void Start() { StartCoroutine(goContol(5.0f)); } void move() { if (go.transform.position.y >= 5.0f) { return; } go.transform.Translate(0, Time.deltaTime * 1, 0); } IEnumerator goContol(float rate) { while (index < transform.childCount) { go = transform.GetChild(index).gameObject; index++; yield return new WaitForSeconds(rate); } } void Update() { move(); } }
2.用协程做一个计时器
思路: 时分秒都是用秒来计算。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Timer : MonoBehaviour { float curSecond; Text timer; int seconds; int secondNum; int miniuteNum; int hourNum; public bool isPause = false; void Start() { timer = transform.GetComponent<Text>(); StartCoroutine(Updata()); } IEnumerator Updata() { while (true) { secondNum++; seconds++; if (secondNum == 60) { secondNum = 0; } yield return new WaitForSeconds(1.0f); } } void Update() { if (isPause == false) { string secstr; string minstr; string hourstr; miniuteNum = seconds % 3600 / 60; hourNum = seconds / 3600; if (secondNum<10) { secstr = "0"+secondNum.ToString(); } else { secstr = secondNum.ToString(); } if (miniuteNum < 10) { minstr = "0" + miniuteNum.ToString(); } else { minstr = miniuteNum.ToString(); } if (hourNum < 10) { hourstr = "0" + hourNum.ToString(); } else { hourstr = hourNum.ToString(); } timer.text = hourstr + ":"+ minstr+":" +secstr; } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。