为什么说是诡异的协程呢?首先从一个案例说起吧,示例如下:
游戏目标:让小车进入到对应颜色屋子里,即可获得一分。(转弯的道路可控)
为了让小车能够平滑转弯,小车的前进方向需要和车子的位置与圆心组成的连线垂直。
首先想到的就是在车子进入到碰撞体和在碰撞体里面都是上述运动方式,离开碰撞体后相当于旋转了90度。
但是当车子在转弯的道路上时,此时将左转弯的路变成右转弯的路,车子就会失控,因为碰撞体消失后对应的事件就不会执行了。
所以想到让车子持续转弯的方法放进协程里面做,小车前进代码和转弯代码如下:
小车前进代码:
public class CarMove : MonoBehaviour { public float Speed = 1f; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { transform.Translate(Vector3.forward * Speed * Time.deltaTime); } }
小车转弯代码:
public class CurveCollider : MonoBehaviour { // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } private void OnCollisionEnter(Collision collision) { if (this.CompareTag("TurnLeft")) { StartCoroutine(CarTurnLeft(collision)); } } IEnumerator CarTurnLeft(Collision collision) { while (true) { Vector3 worldUp = Vector3.up; Vector3 targetPos = collision.transform.position; Vector3 direction = transform.position - targetPos; Vector3 forwardDir = new Vector3(-1.0f, 1.0f, 1.0f); Vector3.OrthoNormalize(ref worldUp, ref direction, ref forwardDir); Quaternion quaternion = Quaternion.identity; quaternion.SetLookRotation(forwardDir); collision.transform.rotation = quaternion; yield return null; Debug.Log(collision.transform.eulerAngles.y); if (collision.transform.eulerAngles.y >= 270 && (collision.transform.eulerAngles.y - 270) <= 1) { quaternion = Quaternion.identity; quaternion.eulerAngles = new Vector3(0.0f, -90.0f, 0.0f); collision.transform.rotation = quaternion; yield break; } } } }
下面先简单介绍一下协程的基本概念:Unity手册:协程
UnityEngine所提供的SDK都只能在单线程中调用,而协程也是单线程的,不同于多线程。
Unity中只代码只要有一个地方代码出现死循环或者运行时间较长,游戏就会卡死。
关于协程其中有这么一句话,很重要:协程优化
因为协程中的局部作用域变量必须在yield
调用中保持一致,所以这些局部作用域变量将被保存到上一级的生成的它们的类中,从而保证在协程的存活期内保留在堆上的地址分配。
好了,现在回到我们的案例,发生了什么问题呢?
当其中一个小车进入到房子后,其中有一个小车没有正常转弯了,并且发生报错,如上图标红的地方,这是为什么呢?
房子的碰撞代码如下:
private void OnCollisionEnter(Collision collision) { if (this.CompareTag(collision.gameObject.tag)) { GameController.Score++; } Destroy(collision.gameObject); }
当小车进入到房子后就会摧毁小车,如果进入的车是对的,就加一分。
报错的行43行是如下代码:
if (collision.transform.eulerAngles.y >= 270 && (collision.transform.eulerAngles.y - 270) <= 1)
这是不是很匪夷所思呢?
因为当小车进入直线轨道时协程已经结束了,怎么协程还在运行呢?
此时你可以想起上面那句话,应该可以猜到了为什么会发生这样。
当Car1进入House碰撞体时,也将Collider存放在同一个地方,之后将这个小车摧毁。
此时小车3正好在执行协程,当从yield 之后的语句开始执行时,由于小车已经被摧毁,所以就报错了。
1、IT大王遵守相关法律法规,由于本站资源全部来源于网络程序/投稿,故资源量太大无法一一准确核实资源侵权的真实性;
2、出于传递信息之目的,故IT大王可能会误刊发损害或影响您的合法权益,请您积极与我们联系处理(所有内容不代表本站观点与立场);
3、因时间、精力有限,我们无法一一核实每一条消息的真实性,但我们会在发布之前尽最大努力来核实这些信息;
4、无论出于何种目的要求本站删除内容,您均需要提供根据国家版权局发布的示范格式
《要求删除或断开链接侵权网络内容的通知》:https://itdw.cn/ziliao/sfgs.pdf,
国家知识产权局《要求删除或断开链接侵权网络内容的通知》填写说明: http://www.ncac.gov.cn/chinacopyright/contents/12227/342400.shtml
未按照国家知识产权局格式通知一律不予处理;请按照此通知格式填写发至本站的邮箱 wl6@163.com