c# lambda调用for循环引用最后一个对象

本文关键字:引用 最后 一个对象 循环 for lambda 调用 | 更新日期: 2023-09-27 17:50:35

我已经研究了这个问题,并且我已经尝试按照之前的几个问题(例如这个问题)的指示修复代码,但它仍然不起作用。虽然我必须说,我检查的所有答案都是2009-2010年的,所以它们可能已经过时了。

这是错误代码:

            foreach(Entity player in players)
            {
                if(player.actions.Count > 0)
                {
                    Entity temp = player;
                    player.isDoingAction = true;
                    Debug.Log(player.name + " started action");
                    player.actions.Dequeue().Execute(() => { temp.isDoingAction = false; Debug.Log(temp.name + " finished"); });
                }
            }

打印如下内容:

Player1 started action
Player2 started action
Player2 finished
Player2 finished

何时应该打印:

Player1 started action
Player2 started action
Player1 finished
Player2 finished

或者类似的

这段代码运行在一个Unity协程函数中。

代码中的大一点的片段:

GameManager.cs

private IEnumerator RunTurn()
{
    ...
    ...
    ...
    for(int i = 0; i < phases; i++)
    {
        //Assign action to each player
        foreach(Entity player in players)
        {
            if(player.actions.Count > 0)
            {
                Entity temp = player;
                player.isDoingAction = true;
                Debug.Log(player.name + " started action");
                player.actions.Dequeue().Execute(() => { temp.isDoingAction = false; Debug.Log(temp.name + " finished"); });
            }
        }
        //Wait for each player to finish action
        foreach(Entity player in players)
        {
            while(player.isDoingAction == true)
            {
                Debug.Log("Waiting for " + player.name);
                yield return null;
            }
        }
    }
    ...
    ...
    ...
}

Action.cs

public override void Execute(System.Action callback)
{
    Move(callback);             
}
private void Move(System.Action callback)
{
    ...
    ...
    ...
    //Move target entity
    target.MoveToPosition(newPosition, mSpeed, callback);
    target.location = newLocation;
    ...
    ...
    ...
}

Entity.cs

public void MoveToPosition(Vector3 position, float speed, System.Action callback)
{
    StartCoroutine(CoMoveToPosition(position, speed, callback));
}
//Move to position
private IEnumerator CoMoveToPosition(Vector3 position, float speed, System.Action callback)
{
    while(position != transform.position)
    {
        transform.position = Vector3.MoveTowards(transform.position, position, speed * Time.deltaTime);
        yield return null;
    }
    //Move finished so use callback
    callback();
}
<<p> 解决方案/strong>

原来Unity中有一个协程和匿名lambda回调的bug。点击此链接了解更多信息。

工作段代码:

foreach(Entity player in players)
{
    if(player.actions.Count > 0)
    {
        player.isDoingAction = true;
        Debug.Log(player.name + " started action");
        System.Func<Entity, System.Action> action = new System.Func<Entity,System.Action>(p =>
        new System.Action(() => { p.isDoingAction = false; Debug.Log(p.name + " finished"); }));
        player.actions.Dequeue().Execute(action(player));
    }
}

c# lambda调用for循环引用最后一个对象

您可以通过以下方式获取该值:

var action = new Func<Entity, Action>(p => 
new Action(() => { p.isDoingAction = false; Debug.Log(p.name + " finished")); })(player);
player.actions.Dequeue().Execute(action);

Try

player.actions.Dequeue().Execute(temp => 
{ temp.isDoingAction = false; 
  Debug.Log(temp.name + " finished"); 
});