我有一款游戏可以计算玩家在远程系统上的操作。为了争论起见,假设这个系统一次只能处理一个动作,但玩家应该能够根据需要排列任意数量的动作。
每当玩家执行动作时,客户端向远程发送请求:
async void ActionAsync(){
string id = await ActionRequestToRemote();
CharacterActions.Add(new CharacterAction(id, currentlySelectedGameobject));
}
获取 id 足够快,但之后需要远程大约 6 秒才能返回新的游戏状态,在此期间所有进一步的等待请求都会被遗忘(例如,玩家在一秒钟内点击 3 次)。
让玩家保持排队动作的最佳方式是什么,同时拖延/安排
await ActionARequestToRemote(id)
的执行直到前一个动作完成?
每当远程处理完成时,调用以下方法开始播放动画等
void UpdateLocalGameState(string Type, bool success)
{
if (success)
{
switch (type)
{
case "ActionA":
LocallyDoActionA(CharacterActions[0]);
break;
case "ActionB":
LocallyDoActionB(CharacterActions[0]);
break;
case "ActionC":
LocallyDoActionC(CharacterActions[0]);
break;
}
}
}
我目前通过列表递归地使自己出队,在玩家点击时忽略请求,并在所有任务执行完成后重新发送它们。但这似乎不够优雅,而且可能有更好的方法?
在我看来你想使用某种
ConcurrentQueue
并允许动作堆积在那里。
像例如
public readonly struct ActionResult
{
public string Type { get; }
public bool Success { get; }
public ActionResult(string type, bool success)
{
Type = type;
Success = success;
}
}
private readonly ConcurrentQueue<CharacterAction> CharacterActions = new ();
private bool isHandlingQueuedActions;
public event Action<ActionResult> onActionResult;
public void SendActionQueued(CharacterAction action)
{
CharacterActions.Enqueue(action);
if(!isHandlingQueuedActions)
{
Task.Run(async ()=> await HandleQueuedActions());
}
}
private async Task HandleQueuedActions()
{
isHandlingQueuedActions = true;
while(CharacterActions.TryDequeue(out var action))
{
ActionResult result = await HoweverYouSubmitTheAction(action);
onActionResult?.Invoke(result);
}
isHandlingQueuedActions = false;
}