我已经研究过这个问题,并且我曾尝试按照几个问题(such as this one)的指示修复代码,但它仍然无法正常工作。虽然我必须说我检查的所有答案都是从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();
}
解决方案
事实证明,Unity中有一个带有协同程序和匿名lambda回调的错误。查看this链接了解更多信息。
工作代码:
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));
}
}
答案 0 :(得分:4)
您可以通过以下方式捕获值:
var action = new Func<Entity, Action>(p =>
new Action(() => { p.isDoingAction = false; Debug.Log(p.name + " finished")); })(player);
player.actions.Dequeue().Execute(action);
答案 1 :(得分:2)
尝试
player.actions.Dequeue().Execute(temp =>
{ temp.isDoingAction = false;
Debug.Log(temp.name + " finished");
});