Unity协程中的意外控制流(检测完成)
Unexpected control flow in Unity coroutine (detecting completion)
我有一个附加到 Unity 5 游戏对象的脚本,当用户单击按钮时,该脚本会按固定量旋转对象。旋转是在协同程序中完成的,以使其随着时间的推移顺利发生。
我想阻止用户对同一对象执行另一次旋转,直到完成第一次旋转。为此,我添加了一个 isRotating
布尔值,在协程启动时设置为 true,在协程完成轮换时设置为 false。代码如下:
using UnityEngine;
using System.Collections;
public class ObjectScript : MonoBehaviour {
private bool isRotating = false;
/* Rotate the object 90 degrees around the x axis centered on the origin */
IEnumerator RotateObject() {
isRotating = true;
var updateRotation = 0.0f; // amount to rotate this tick
for (var totalRotation = 0.0f; totalRotation <= 90.0f; totalRotation += updateRotation) {
updateRotation = 90.0f * (Time.deltaTime / 0.5f);
if (totalRotation + updateRotation > 90.0f) {
updateRotation = 90.0f - totalRotation;
}
transform.RotateAround (Vector3.zero, Vector3.right, updateRotation);
yield return null;
}
isRotating = false; // This line is never reached
}
void Update () {
if (Input.GetKeyDown(KeyCode.X) && !isRotating) {
StartCoroutine (RotateObject());
}
}
}
我的问题是从未到达 isRotating = false
行,因此 isRotating
被保留设置为 true
,即使在协程完成旋转对象之后也是如此。 (我通过在行上放置调试断点来检查这一点,这些断点永远不会被击中)。所以一旦对象旋转了一次,它就再也不会旋转了。
为什么控件永远不会到达循环体之外的行?
updateRotation = 90.0f - totalRotation;
=> totalRotation + updateRotation = 90
每次 totalRotation + updateRotation > 90.0f
重新分配 updateRotation
以便下一次迭代 totalRotation + updateRotation = 90
=> totalRotation <= 90.0f
永远不会 false
我发现了错误。
在 RotateObject
内的主循环中,我正在检查条件 totalRotation <= 90.0f
。但是,我已将代码添加到循环中以确保我没有过度旋转:
if (totalRotation + updateRotation > 90.0f) {
updateRotation = 90.0f - totalRotation;
}
这可以很好地防止过度旋转,但是因为我每次通过添加 updateRotation
:
来更新循环变量 totalRotation
for (...; ...; totalRotation += updateRotation) {
totalRotation
本质上是 "clamped",并且永远不会超过 90.0f——因此循环永远不会退出。
因此,解决方法是将我的循环条件更改为 <
而不是 <=
,例如:
for (var totalRotation = 0.0f; totalRotation < 90.0f; totalRotation += updateRotation) {
我有一个附加到 Unity 5 游戏对象的脚本,当用户单击按钮时,该脚本会按固定量旋转对象。旋转是在协同程序中完成的,以使其随着时间的推移顺利发生。
我想阻止用户对同一对象执行另一次旋转,直到完成第一次旋转。为此,我添加了一个 isRotating
布尔值,在协程启动时设置为 true,在协程完成轮换时设置为 false。代码如下:
using UnityEngine;
using System.Collections;
public class ObjectScript : MonoBehaviour {
private bool isRotating = false;
/* Rotate the object 90 degrees around the x axis centered on the origin */
IEnumerator RotateObject() {
isRotating = true;
var updateRotation = 0.0f; // amount to rotate this tick
for (var totalRotation = 0.0f; totalRotation <= 90.0f; totalRotation += updateRotation) {
updateRotation = 90.0f * (Time.deltaTime / 0.5f);
if (totalRotation + updateRotation > 90.0f) {
updateRotation = 90.0f - totalRotation;
}
transform.RotateAround (Vector3.zero, Vector3.right, updateRotation);
yield return null;
}
isRotating = false; // This line is never reached
}
void Update () {
if (Input.GetKeyDown(KeyCode.X) && !isRotating) {
StartCoroutine (RotateObject());
}
}
}
我的问题是从未到达 isRotating = false
行,因此 isRotating
被保留设置为 true
,即使在协程完成旋转对象之后也是如此。 (我通过在行上放置调试断点来检查这一点,这些断点永远不会被击中)。所以一旦对象旋转了一次,它就再也不会旋转了。
为什么控件永远不会到达循环体之外的行?
updateRotation = 90.0f - totalRotation;
=> totalRotation + updateRotation = 90
每次 totalRotation + updateRotation > 90.0f
重新分配 updateRotation
以便下一次迭代 totalRotation + updateRotation = 90
=> totalRotation <= 90.0f
永远不会 false
我发现了错误。
在 RotateObject
内的主循环中,我正在检查条件 totalRotation <= 90.0f
。但是,我已将代码添加到循环中以确保我没有过度旋转:
if (totalRotation + updateRotation > 90.0f) {
updateRotation = 90.0f - totalRotation;
}
这可以很好地防止过度旋转,但是因为我每次通过添加 updateRotation
:
totalRotation
for (...; ...; totalRotation += updateRotation) {
totalRotation
本质上是 "clamped",并且永远不会超过 90.0f——因此循环永远不会退出。
因此,解决方法是将我的循环条件更改为 <
而不是 <=
,例如:
for (var totalRotation = 0.0f; totalRotation < 90.0f; totalRotation += updateRotation) {