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

八球游戏刚体停球检测问题:如何判断所有球速度低于0.1?

八球台球游戏:检测所有球停止运动的问题解决

我正在开发一款八球台球游戏,需要检测台面上所有球何时停止运动。我尝试使用以下代码,但已停止的球的计数(Balls_Stopped)不断增长到极大数值,而实际数值应不超过16。

原代码:

IEnumerator CheckObjectsHaveStopped()
{
    bool allSleeping = false;
    Rigidbody[] GOS = FindObjectsOfType(typeof(Rigidbody)) as Rigidbody[];
    while (!allSleeping)
    {
        allSleeping = true;
        foreach (Rigidbody GO in GOS)
        {
            if (GO.velocity.magnitude <= 0.1)
            {
                Balls_Stopped += 1;
                Debug.Log("Balls Stopped = " + Balls_Stopped);
                yield return null;
            }
        }
    }

    if (Balls_Stopped == Balls_Left)
    {
        print("All objects sleeping");
        //Do something here
    }
}

问题根源

  1. 计数逻辑错误:每次循环遍历刚体时,只要球满足速度条件就累加Balls_Stopped,同一个球每帧都会被重复计数,导致数值疯涨。
  2. 循环逻辑漏洞:allSleeping初始设为true,但没有处理“球未停止”的情况——只要有一个球还在动,应该把allSleeping设回false,否则循环会卡死。
  3. 帧暂停位置错误:yield return null放在foreach内部,会导致每次检测到一个停止的球就暂停一帧,无法一次性完成所有球的状态检测。

修正方案

方案1:每帧重新统计停止的球数(推荐)

这种方式直接每帧计算当前停止的球数量,避免累加错误,同时兼顾旋转状态的检测:

IEnumerator CheckObjectsHaveStopped()
{
    Rigidbody[] allBalls = FindObjectsOfType<Rigidbody>();
    while (true)
    {
        int currentStoppedCount = 0;
        bool allStopped = true;

        foreach (Rigidbody ball in allBalls)
        {
            // 同时检测线速度和角速度,避免球旋转但不移动的误判
            if (ball.velocity.magnitude <= 0.1f && ball.angularVelocity.magnitude <= 0.1f)
            {
                currentStoppedCount++;
            }
            else
            {
                allStopped = false;
            }
        }

        Debug.Log("当前停止的球数: " + currentStoppedCount);

        if (allStopped)
        {
            print("所有球已停止运动");
            // 在这里添加球停止后的逻辑,比如允许玩家再次击球
            break;
        }

        yield return null; // 每帧检测一次
    }
}

方案2:用集合标记已停止的球(适合跟踪单个球状态)

如果需要单独记录哪些球已经停止,可以用HashSet来标记,避免重复计数:

HashSet<Rigidbody> stoppedBalls = new HashSet<Rigidbody>();

IEnumerator CheckObjectsHaveStopped()
{
    Rigidbody[] allBalls = FindObjectsOfType<Rigidbody>();
    while (stoppedBalls.Count < allBalls.Length)
    {
        stoppedBalls.Clear(); // 每帧重新标记当前停止的球

        foreach (Rigidbody ball in allBalls)
        {
            if (ball.velocity.magnitude <= 0.1f && ball.angularVelocity.magnitude <= 0.1f)
            {
                stoppedBalls.Add(ball);
            }
        }

        Debug.Log("当前停止的球数: " + stoppedBalls.Count);

        if (stoppedBalls.Count == allBalls.Length)
        {
            print("所有球已停止运动");
            // 执行后续逻辑
            break;
        }

        yield return null;
    }

    stoppedBalls.Clear(); // 重置集合,方便下次检测使用
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 22:01:26