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

Unity调试模式与运行模式骰子结果不一致问题求助

问题诊断与解决方案

你的核心问题是异步任务的等待逻辑依赖不可靠的状态变量,且GetDiceValues中的协程完全无效,导致运行模式下RollDice()没有真正等待骰子停止就继续执行后续代码。

问题根源

  1. WaitUntilStoppedMoving依赖外部状态变量:原代码中通过_hasStoppedRolling判断是否停止,但如果这个变量的设置逻辑(你未贴出的部分)在运行模式下因帧率或碰撞检测时机问题未及时触发,会导致任务提前结束。
  2. GetDiceValues中的协程无效:调用StartCoroutine(DelayResult(die))后函数立刻返回,不会等待协程完成,因此无法解决骰子未停止的问题。
  3. 旧骰子引用残留:销毁旧骰子后未清空spawnedDice列表,可能导致空引用或错误取值。

分步解决方案

1. 修复Dice类的等待逻辑,直接检测刚体状态

把WaitUntilStoppedMoving改为直接检测刚体的速度,无需依赖外部状态变量,确保只有当骰子完全静止时才结束任务:

public async Task WaitUntilStoppedMoving()
{
    // 阈值可根据需求调整,确保骰子完全静止
    const float velocityThreshold = 0.01f;
    
    // 等待刚体线速度和角速度都低于阈值
    while (diceRb.velocity.magnitude > velocityThreshold || diceRb.angularVelocity.magnitude > velocityThreshold)
    {
        // 每一帧等待,确保在Unity主线程调度
        await Task.Delay(TimeSpan.FromSeconds(Time.deltaTime));
    }
    
    // 如果仍需要使用_hasStoppedRolling,在此处设置
    _hasStoppedRolling = true;
}

同时在Dice的Awake中初始化状态:

private void Awake()
{
    diceRb = GetComponent<Rigidbody>();
    _hasStoppedRolling = false;
}

2. 简化DiceThrower的GetDiceValues

因为RollDice()中已经通过await Task.WhenAll(rollTasks)确保所有骰子都停止了,所以GetDiceValues不需要再检测是否停止,直接取值即可:

public List<int> GetDiceValues()
{
    List<int> diceValues = new List<int>();
    foreach (var die in spawnedDice)
    {
        if (die != null)
        {
            diceValues.Add(die.GetComponent<Dice>().GetNumberOnTopFace());
        }
    }
    return diceValues;
}

3. 清理DiceThrower的旧骰子引用

销毁旧骰子后清空spawnedDice列表,避免残留空引用:

public async Task RollDice()
{
    if (diceToThrow == null)
    {
        Debug.LogError("No dice to throw assigned. Please assign a dice prefab.");
        return;
    }

    foreach (var die in spawnedDice)
    {
       Destroy(die);
    }
    // 清空列表,移除已销毁的骰子引用
    spawnedDice.Clear();

    List<Task> rollTasks = new List<Task>();

    for (int i = 0; i < amountOfDice; i++)
    {
        Dice dice = Instantiate(diceToThrow, transform.position, transform.rotation);
        spawnedDice.Add(dice.gameObject);
        rollTasks.Add(dice.RollDice(throwForce, rollForce, i));
    }

    await Task.WhenAll(rollTasks);

    rollButtonClicked = false;
}

额外注意事项

  • 确保Dice类的GetNumberOnTopFace()逻辑正确,在骰子静止时能准确识别顶面数值(比如通过射线检测或碰撞体判断)。
  • 运行模式下测试时,可添加Debug.Log打印骰子的速度和_hasStoppedRolling状态,验证等待逻辑是否正常触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 21:06:01