You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

异步方法执行调度:游戏远程动作队列处理方案咨询

最优动作串行调度实现方案

核心思路是通过线程安全队列缓存玩家动作+异步任务串行链,确保远程系统同一时间仅处理一个动作,同时不丢失玩家的任何操作请求,替代递归遍历的方案:

实现步骤与代码

1. 新增核心字段

在客户端逻辑类中添加以下字段,用于维护动作队列、跟踪执行状态和同步远程回调:

// 线程安全的待处理动作队列,存储玩家选中的游戏对象
private readonly ConcurrentQueue<GameObject> _pendingActions = new ConcurrentQueue<GameObject>();
// 跟踪当前正在执行的异步任务链,避免重复调度
private Task _currentExecutionTask = Task.CompletedTask;
// 同步远程处理完成的信号量,确保动作按顺序执行
private readonly SemaphoreSlim _actionCompletedSignal = new SemaphoreSlim(0, 1);

2. 修改玩家动作触发逻辑

玩家点击时不再直接发起远程请求,而是将动作加入队列并启动调度:

// 玩家点击动作按钮时调用此方法
void OnPlayerActionClicked()
{
    _pendingActions.Enqueue(currentlySelectedGameobject);
    // 启动队列处理,用_=忽略返回任务避免警告
    _ = ProcessActionQueueAsync();
}

3. 实现串行队列处理逻辑

这个方法会循环处理队列中的动作,确保前一个动作的完整流程(发送请求→远程处理→本地更新)完成后,再处理下一个:

private async Task ProcessActionQueueAsync()
{
    // 用原子操作确保只有一个线程在处理队列,防止重复调度
    if (Interlocked.CompareExchange(ref _currentExecutionTask, Task.CompletedTask, Task.CompletedTask) != Task.CompletedTask)
        return;

    try
    {
        while (_pendingActions.TryDequeue(out var selectedObj))
        {
            try
            {
                // 发送远程请求获取动作ID
                string actionId = await ActionRequestToRemote();
                // 将动作加入本地列表
                CharacterActions.Add(new CharacterAction(actionId, selectedObj));
                
                // 等待远程处理完成(即UpdateLocalGameState被调用)
                await _actionCompletedSignal.WaitAsync();
                
                // 移除已完成的动作(对应UpdateLocalGameState中取第一个元素的逻辑)
                if (CharacterActions.Count > 0)
                    CharacterActions.RemoveAt(0);
            }
            catch (Exception ex)
            {
                // 处理请求失败场景:记录日志、提示玩家,避免队列阻塞
                Debug.LogError($"动作处理失败: {ex.Message}");
                if (CharacterActions.Count > 0)
                    CharacterActions.RemoveAt(0);
            }
        }
    }
    finally
    {
        // 重置任务状态,允许下次调度
        Interlocked.Exchange(ref _currentExecutionTask, Task.CompletedTask);
    }
}

4. 修改本地状态更新方法

在远程回调完成后释放信号量,通知队列可以处理下一个动作:

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;
        }
    }
    
    // 释放信号量,允许队列处理下一个动作
    _actionCompletedSignal.Release();
}

方案优势

  • 无递归逻辑,代码结构清晰易维护
  • 线程安全队列确保玩家快速点击的动作不会丢失
  • 用信号量精准同步远程处理流程,保证动作严格按顺序执行
  • 异常处理逻辑避免单个动作失败导致整个队列阻塞

内容的提问来源于stack exchange,提问作者z3po

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 14:45:32