void 一个函数名(){
StartCoroutine(“TryTryThis()”);
}
IEnumerator TryTryThis(){
一些内容;
yield return 一些内容; // or yield return StartCoroutine(MyFunc);
other;
}
void Fun()
{
while(true)
{
debug.log("进入循环")
}
}
那么会一直进入循环。
但是如果把这个Fun()的类型,改为IEnumerator,
IEnumerator Fun()
{
while(true)
{
debug.log("进入循环")
}
}
然后想要调用这个迭代接口(IEnumerator ),就再其他函数中,写StartCoroutine(Fun())
void Start()
{
StartCoroutine(Fun());
}
IEnumerator Fun()
{
while(true)
{
debug.log("进入循环")
}
}
yield return 语句的用处很广,它的主要作用是在合适的时间给你一定的返回结果。比如如果在这里运用一个yield return new WaitForSeconds(0.5f);,也就是说,这个名叫Fun()的循环中,有0.5f可以供其他代码运行。每循环一次,每输出一次“进入循环",就有0,5秒,可以让其他代码行走。所以即使是无限循环,进程也不会卡死。
这就是协程:Coroutine.
举个例子,在Unity中,要写一个迭代接口IENUMERATOR,
void Start()
{
string[]messages={"a","b","c","d","e","f","g","h","i"};
StartCoroutine(Fun(messages,9.5f));
}
IEnumerator PrintMessages(string[]messages,float delay)
{
foreach (string msg in messages
{在对每一个messages数据串里面的内容foreach循环时,都要间隔delay秒。
printf("已阅读一条");
yield return new WaitForSeconds(delay);
}
}
在这个例子,IENUMERATOR制造循环,StartCoroutine调用循环。
void Update()
{
if(Input.GetKeyDown(KeyCode.space)
{
StartCoroutine(Move(Random.Position随机一个位置,8));
}
}
IEnumerator Move( Vector3 destination,float speed)
{
while(transform.position!=destination)
{
transform.position=Vector3.MoveTowards(transform.position,destination目标位置,speed*time.deltatime);
}
yield return null;每次循环一次后,暂缓一帧再执行,预防瞬间移动
}
物体向目标移动:再次利用迭代接口IEnumerator建立一个while循环:从transform.position出发,向着目标移动,一次移动固定的距离,移动到了,结束while循环。
再举个例子,对象池管理子弹,原本想利用list的方式,每次调用pool内的list[0],然后把GameObject给bullet预设体。但是问题是,虽然它可以生成新的子弹预设体,也可以按需消失。但是它无法移动。不是很方便,只能叠在生成位置,也就是枪口上。
于是用了这个方法。
public void returnBullet(Projectile targetBullet)
{
StartCoroutine(returnBulletToPoolLater(targetBullet));
}
IEnumerator returnBulletToPoolLater(Projectile targetBullet)
{Projectile是写挂载在bullet上面的脚本。在这个脚本下生成一个targetBullet
yield return new WaitForSeconds(3f);
三秒一个循环。
if (targetBullet != null)
如果子弹非空
bulletPool.ReturnInstance(targetBullet, poolPositon);
那么就要在poolPosition上制造一个子弹(targetBullet)
}
配置在Gun上面的Gun.cs全文如下:
public UnityEvent OnShoot;
public Transform muzzle;
[Header("Bullet Setting")]
public Projectile projectile;
public float msBetweenShots = 100; //子弹发射间隔
public float muzzleVelocity = 35; //子弹速度
public int bulletNumber; //一个弹夹子弹数
protected float nextShotTime;
[Header("BulletPool")]
public Transform poolPositon;
public ObjectPool bulletPool;
public GameObject fireEffect;
private void Start()
{
poolPositon = GameObject.FindGameObjectWithTag("BulletPool").transform;
带有BulletPool的TAG的物体,把这种物体的位置传给PoolPosition.
}
public virtual void GenerateBullet()
{
}
public virtual void Shoot()
{
if (Time.time > nextShotTime)
{
nextShotTime = Time.time + msBetweenShots / 1000;
OnShoot.Invoke();nvoke是延时调用函数
GenerateBullet();
其他cs里设定了,左键,激发这个脚本里面的Shoot
}
}
public void returnBullet(Projectile targetBullet)
{
StartCoroutine(returnBulletToPoolLater(targetBullet));
}
IEnumerator returnBulletToPoolLater(Projectile targetBullet)
{
yield return new WaitForSeconds(3f);
if (targetBullet != null)
bulletPool.ReturnInstance(targetBullet, poolPositon);
}
public void returnHitBulletToPool(Projectile targetBullet)
{
targetBullet.gameObject.SetActive(false);
//if (targetBullet != null)
//bulletPool.ReturnInstance(targetBullet, muzzle);
}
}