Unity之"诡异"的协程
为什么说是诡异的协程呢?首先从一个案例说起吧,示例如下:
游戏目标:让小车进入到对应颜色屋子里,即可获得一分。(转弯的道路可控)
为了让小车能够平滑转弯,小车的前进方向需要和车子的位置与圆心组成的连线垂直。
首先想到的就是在车子进入到碰撞体和在碰撞体里面都是上述运动方式,离开碰撞体后相当于旋转了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 之后的语句开始执行时,由于小车已经被摧毁,所以就报错了。
最新文章
- mysql 常用自定义函数解析
- js&#39;中的apply和call和bind的用法
- EntityFramework系列:SQLite.CodeFirst自动生成数据库
- Jmeter中察看结果树中的响应数据,中文显示乱码问题处理
- ps esc 问题
- 14 Using Indexes and Clusters
- java使用Thumbnailator操作图片
- [LeetCode][Python]Longest Palindromic Substring
- kvm 存储
- swift笔记 (三) —— 字符和字符串
- 【渗透测试】hydra使用小结
- Java Swing 图形界面实现验证码(验证码可动态刷新)
- Struts2学习笔记(九)——数据校验
- jvm系列 (五) ---类加载机制
- String总结
- Mysql 杀死sleep进程
- jar包在控制台下运行
- dijkstra算法(贪心算法)——解决最短路径问题
- Leetcode 计划
- javaweb学习1——加密
热门文章
- Spring 10: AspectJ框架 + @Before前置通知
- 【c#】仅1600行代码 2D魔方游戏源码-纯WinForm
- Linux安装Jenkins及配置svn使用
- AtCoder Beginner Contest 265(D-E)
- 免费内网穿透服务Localtunnel
- C++中的STL大法整理
- Java常用类的使用
- stm32fxx_hal_i2c.c解读之HAL_I2C_Mem_Write
- 从 Yum 更新中排除特定/某些包的三种方法
- 使用sonarqube对java项目进行分析