C# 在IEnumerator协同程序中使用闭包进行澄清

C# 在IEnumerator协同程序中使用闭包进行澄清,c#,unity3d,closures,functor,coroutine,C#,Unity3d,Closures,Functor,Coroutine,我有两个IEnumerator协同程序,它们非常相似,应该结合使用: A: B: 唯一的两个区别是变量totalTime\u AvstotalTime\u B和timeLeft\u AvstimeLeft\u B。这些变量不在此函数范围内 我模块化这个协程的问题是,timeLeft\u A和timeLeft\u B的增量值需要应用于这个函数之外,所以我需要以某种方式向它们传递一个引用 用户“Kurt Dekker”在中发布了一个很棒的解决方案,但我在将其应用于代码时遇到了问题。他说“使用闭包(函

我有两个IEnumerator协同程序,它们非常相似,应该结合使用:

A:

B:

唯一的两个区别是变量
totalTime\u A
vs
totalTime\u B
timeLeft\u A
vs
timeLeft\u B
。这些变量不在此函数范围内

我模块化这个协程的问题是,
timeLeft\u A
timeLeft\u B
的增量值需要应用于这个函数之外,所以我需要以某种方式向它们传递一个引用

用户“Kurt Dekker”在中发布了一个很棒的解决方案,但我在将其应用于代码时遇到了问题。他说“使用闭包(函子)允许协同程序通过回调修改它”:

我不明白的是,如果我只需要使用回调函数,那么如何在IEnumerator内部引用/修改传入的int的实际值。例如,执行以下操作:

while(callback > 0){
或:


非常感谢您的帮助。

我想这可能会回答您关于如何在协同程序中使用
系统的问题

public float timeLeft_A = 0f;
public float timeLeft_B = 0f;

public float totalTime_A = 15f;
public float totalTime_B = 20f;

// Start is called before the first frame update
void Start()
{
    StartCoroutine(Cooldown(totalTime_A, (i) =>
    {
        timeLeft_A = i;
    }));

    StartCoroutine(Cooldown(totalTime_B, (i) =>
    {
        timeLeft_B = i;
    }));
}

IEnumerator Cooldown(float totalTime, Action<float> callback)
{
    var timeLeft = totalTime;
    while (timeLeft > 0)
    {
        yield return new WaitForSeconds(1);
        callback(--timeLeft);
    }
}
基本上,当您调用
startcroutine
时,您将计数器的最大时间作为一个普通参数和一个回调,这个回调将浮点作为参数(这里是i

如果调用
callback(-timeLeft)
在您的协同程序中,它将执行您传入的
System.Action

在这里,它将
timeLeft\u A
timeLeft\u B
设置为相应协同程序的
timeLeft
变量

public float timeLeft_A = 0f;
public float timeLeft_B = 0f;

public float totalTime_A = 15f;
public float totalTime_B = 20f;

// Start is called before the first frame update
void Start()
{
    StartCoroutine(Cooldown(totalTime_A, (i) =>
    {
        timeLeft_A = i;
    }));

    StartCoroutine(Cooldown(totalTime_B, (i) =>
    {
        timeLeft_B = i;
    }));
}

IEnumerator Cooldown(float totalTime, Action<float> callback)
{
    var timeLeft = totalTime;
    while (timeLeft > 0)
    {
        yield return new WaitForSeconds(1);
        callback(--timeLeft);
    }
}
public float timeLeft_A=0f;
公共浮动时间限制B=0f;
公共浮动总时间_A=15f;
公共浮动总时间_B=20f;
//在第一帧更新之前调用Start
void Start()
{
开始例行程序(冷却时间(总时间)A,(i)=>
{
时间间隔A=i;
}));
开始例行程序(冷却时间(总时间)_B,(i)=>
{
时间间隔B=i;
}));
}
IEnumerator冷却(浮动总时间,动作回调)
{
var timeLeft=总时间;
而(时间间隔>0)
{
返回新的WaitForSeconds(1);
回调(-timeLeft);
}
}

根据Antoine Thiry的回答,我只是把我的实现放在这里给后代看

private static int totalTime_A = 45; // Num seconds
private int timeLeft_A = totalTime_A;
private static int totalTime_B = 30; // Num seconds
private int timeLeft_B = totalTime_B;

// Pass in totalTime separately from the callback (totalTime doesn't need to change)
IEnumerator CountDown(int totalTime, Action<int> callback){
  int timeLeft = totalTime; // Create new local var here to operate on it
  while (timeLeft > 0) {
    yield return new WaitForSeconds(1);
    callback(--timeLeft); // Then put the local var into callback after operating on it
  }
}

我真的不明白你在问什么。。。你需要给你的协同程序传递一个参数吗?好的,我现在明白了:)倒计时变量是在协同程序之外修改的,对吗?是的,我基本上需要通过引用将
timeLeft\u a
传递到
countdown\u a()
中(值需要全局更改)。但是我想要
countdown\u a()
CountDown_B()
是同一个函数,所以可能
CountDown()
。因此,全局变量不能在内部显式命名。Ho ok nevermind。。我会尽力为你找到解决办法:)非常感谢你花时间做这件事!我很快就会试试的。
while(callback > 0){
callback--;
public float timeLeft_A = 0f;
public float timeLeft_B = 0f;

public float totalTime_A = 15f;
public float totalTime_B = 20f;

// Start is called before the first frame update
void Start()
{
    StartCoroutine(Cooldown(totalTime_A, (i) =>
    {
        timeLeft_A = i;
    }));

    StartCoroutine(Cooldown(totalTime_B, (i) =>
    {
        timeLeft_B = i;
    }));
}

IEnumerator Cooldown(float totalTime, Action<float> callback)
{
    var timeLeft = totalTime;
    while (timeLeft > 0)
    {
        yield return new WaitForSeconds(1);
        callback(--timeLeft);
    }
}
private static int totalTime_A = 45; // Num seconds
private int timeLeft_A = totalTime_A;
private static int totalTime_B = 30; // Num seconds
private int timeLeft_B = totalTime_B;

// Pass in totalTime separately from the callback (totalTime doesn't need to change)
IEnumerator CountDown(int totalTime, Action<int> callback){
  int timeLeft = totalTime; // Create new local var here to operate on it
  while (timeLeft > 0) {
    yield return new WaitForSeconds(1);
    callback(--timeLeft); // Then put the local var into callback after operating on it
  }
}
// timeLeft_A and timeLeft_B change globally
IEnumerator Countdown_A = CountDown(totalTime_A, (i) => { timeLeft_A = i; });
IEnumerator Countdown_B = CountDown(totalTime_B, (i) => { timeLeft_B = i; });
StartCoroutine(Countdown_A);
StopCoroutine(Countdown_A);
StartCoroutine(Countdown_B);
StopCoroutine(Countdown_B);