C# 协同程序和范围
在接收到事件后使用协同路由进行延迟。 延迟之后,我应该将私有布尔值“\u isActive”重置为false,但这永远不会发生。 这可能是由于范围问题吗 这是我的密码C# 协同程序和范围,c#,unity3d,C#,Unity3d,在接收到事件后使用协同路由进行延迟。 延迟之后,我应该将私有布尔值“\u isActive”重置为false,但这永远不会发生。 这可能是由于范围问题吗 这是我的密码 using UnityEngine; using System.Collections; using System; IEnumerator coroutine; bool _isActive; void Awake() { _isActive = false; coroutine = MyDelay(); }
using UnityEngine;
using System.Collections;
using System;
IEnumerator coroutine;
bool _isActive;
void Awake()
{
_isActive = false;
coroutine = MyDelay();
}
private bool MyEventhandler(IEvent evt)
{
StartCoroutine(coroutine);
_isActive = true;
Debug.Log("Yes event received");
}
IEnumerator MyDelay()
{
yield return new WaitForSeconds(2.0f);
Debug.Log("Yes delay complete");
_isActive = false;//private class variable _isActive does not get reset to false
}
void Update(){
Debug.Log(" _isActive = " + _isActive);//_isActive gets set to true but never gets reset to false!!
}
对于初学者来说,您的代码无法编译,您没有在
MyEventhandler
中返回bool
值
但这并不是代码不起作用的原因,因为在第一次调用后,您从未创建一个新的协同路由,您总是尝试重新启动同一个协同路由实例
您应该这样做:
private bool MyEventhandler(IEvent evt){
StopCoroutine(coroutine);//可选-如下所示
coroutine=MyDelay();
启动程序(协同程序);
_isActive=true;
Debug.Log(“收到是事件”);
返回-激活;
}
stopcroutine(协同路由)
用于停止以前运行的协同程序,因此每次引发事件时,延迟将重置为2秒。如果您不想在延迟计时器结束之前重置它,即使引发了其他事件,也不要停止协程
然后,coroutine=MyDelay()
用于创建对同一IEnumerator
方法的另一个实例的新引用,这样当您启动它时,您就从一开始就开始启动它,并尝试重新启动一个已经到达终点的实例,而该实例根本不做任何事情
无论如何我都会移动\u isActive=true代码>在MyDelay()
的开头,因此,通过只读取该方法,可以清楚地看到该协同程序将执行什么操作
编辑:我将试着解释为什么需要创建一个新的引用来让它工作
Unity中的
IEnumerator只有两个可访问的工作元素:MoveNext()
和Current
(Reset()
不工作)。
正是由于有了MoveNext()
,Unity才能使协同程序正常工作
IEnumerator
的工作方式是这样的:它是一组只能按顺序访问的对象:第一次初始化时,Current
指向第一个对象之前的元素,然后要访问下一个元素,需要调用MoveNext()
,依此类推。在Unity之外,您可以使用reset()
重置当前对象(使其返回到第一个元素),但正如我所说,这在Unity中不起作用
这就是在Unity中执行协程的方式:启动时,Unity执行所有代码,直到它到达yield return
指令-这告诉Unity需要从哪个点重新开始执行剩余的代码。基本上,如果您有这样的代码:
IEnumerator MyCoroutine(){
//做事
收益返回空;
//做事2
返回新的等待秒(1f);
//做事
}
结果是:
从Coroutine()
开始:此时,枚举数位于第一个元素之前start例程
- 第一个
在枚举器上被调用,因此MoveNext()
成为Current
并被执行Do Stuff#1
-此时,Unity被指示中断代码的执行,直到通过一帧,执行将在下一次yield return null
回调结束时开始Update
- 在执行下一个
之后,Unity在Update()
上执行一个MyCoroutine()
,它将使当前的MoveNext()
等于
,并将执行它Do Stuff 2
返回新的WaitForSeconds(1f)代码>被命中-现在Unity被指示在1秒后执行
(因此它将通过使用MoveNext()
检查时间差,尝试在两次Unity回调之间进行匹配)time.deltaTime
- 1秒过后,调用
,执行MoveNext()
Do Stuff#3
现在,协同程序已经结束,但是如果您通过引用启动协同程序,那么
IEnumerator
不会永远消失。因为除非再次赋值,否则引用将保持不变,所以即使您尝试使用start例程(reference)
,Unity也会立即在该枚举器上执行MoveNext()
,但在您点击的最后一个Current
之后没有任何元素,所以它不会执行任何东西,因为没有什么可执行的。对于初学者,您的代码无法编译,您没有在MyEventhandler
中返回bool
值
但这并不是代码不起作用的原因,因为在第一次调用后,您从未创建一个新的协同路由,您总是尝试重新启动同一个协同路由实例
您应该这样做:
private bool MyEventhandler(IEvent evt){
StopCoroutine(coroutine);//可选-如下所示
coroutine=MyDelay();
启动程序(协同程序);
_isActive=true;
Debug.Log(“收到是事件”);
返回-激活;
}
stopcroutine(协同路由)
用于停止以前运行的协同程序,因此每次引发事件时,延迟将重置为2秒。如果您不想在延迟计时器结束之前重置它,即使引发了其他事件,也不要停止协程
然后,coroutine=MyDelay()
用于创建对同一IEnumerator
方法的另一个实例的新引用,这样当您启动它时,您就从一开始就开始启动它,并尝试重新启动一个已经到达终点的实例,而该实例根本不做任何事情
无论如何我都会移动\u isActive=true代码>在MyDelay()
的开头,因此,通过只读取该方法,可以清楚地看到该协同程序将执行什么操作
编辑:我将试着解释为什么需要创建一个新的引用来让它工作
伊努梅拉