代码之家  ›  专栏  ›  技术社区  ›  Lews Therin

当所有骰子停止移动时检测

  •  1
  • Lews Therin  · 技术社区  · 6 年前

    这似乎是个很简单的问题,但我很难解决。我在掷骰子( GameObject s)并尝试检测它们何时都停止移动(这样我就可以计算分数)。

    以下是我的尝试:

    public class GameManager : MonoBehaviour
    {
        public GameObject[] _dice;
    
        public Vector3 _rollStartPosition;
        public float _rollForce;
        public float _rollTorque;
    
        bool anyDieIsMoving = false;
    
        void FixedUpdate()
        {
            if (!anyDieIsMoving && Input.GetMouseButtonDown(0))
                RollDice();
        }
    
        void RollDice()
        {
            foreach (var die in _dice)
            {
                // Roll() adds force and torque from a given starting position
                die.GetComponent<Die>()
                   .Roll(_rollStartPosition, Random.onUnitSphere * _rollForce, Random.onUnitSphere * _rollTorque);
            }
    
            StartCoroutine(CheckIfDiceAreMoving());
    
            // Calculate score and do something with it...
        }
    
        IEnumerator CheckIfDiceAreMoving()
        {
            foreach (var die in _dice)
            {
                var dieRigidbody = die.GetComponent<Rigidbody>();
                if (!dieRigidbody.IsSleeping())
                {
                    anyDieIsMoving = true;
                    yield return null;
                }
            }
        }
    }
    

    上面代码的问题是,它会在所有骰子停止移动之前立即尝试计算分数(我通过添加一堆 Debug.Log() 陈述)。

    在计算分数之前,我怎么能等所有的骰子都停止移动呢?

    3 回复  |  直到 6 年前
        1
  •  2
  •   Programmer    6 年前

    你必须做 RollDice 协程函数,然后您可以生成或等待 CheckIfDiceAreMoving 要返回的函数 yield return . 更好的是,把 if (!dieRigidbody.IsSleeping()) 进入之内 while (!dieRigidbody.IsSleeping()) 所以 检查是否正在移动骰子 直到所有骰子停止移动,函数才会退出。另外,检查 Update 函数而不是 FixedUpdate 用来移动的 Rigidbody .

    这是rafactored代码:

    public class GameManager : MonoBehaviour
    {
        public GameObject[] _dice;
    
        public Vector3 _rollStartPosition;
        public float _rollForce;
        public float _rollTorque;
        bool doneRolling = true;
    
        void Update()
        {
            if (doneRolling && Input.GetMouseButtonDown(0))
            {
                StartCoroutine(RollDice());
            }
        }
    
        IEnumerator RollDice()
        {
            doneRolling = false;
    
            foreach (var die in _dice)
            {
                // Roll() adds force and torque from a given starting position
                die.GetComponent<Die>()
                   .Roll(_rollStartPosition, Random.onUnitSphere * _rollForce, Random.onUnitSphere * _rollTorque);
            }
    
            //Wait until all dice tops moving
            yield return CheckIfDiceAreMoving();
    
    
            // Calculate score and do something with it...
    
    
            //Set doneRolling to true so that we call this funtion again
            doneRolling = true;
        }
    
        IEnumerator CheckIfDiceAreMoving()
        {
            foreach (var die in _dice)
            {
                var dieRigidbody = die.GetComponent<Rigidbody>();
                //Wait until all dice stops moving
                while (!dieRigidbody.IsSleeping())
                {
                    yield return null;
                }
            }
        }
    }
    
        2
  •  1
  •   siusiulala    6 年前

    掷骰子() ,在获得状态前计算得分 任何偏差 . 我想你把计算分数移到协程上。

    void RollDice()
    {
        foreach (var die in _dice)
        {
            // Roll() adds force and torque from a given starting position
            die.GetComponent<Die>()
               .Roll(_rollStartPosition, Random.onUnitSphere * _rollForce, Random.onUnitSphere * _rollTorque);
        }
    
        StartCoroutine(CheckIfDiceAreMoving());
    
    }
    
    IEnumerator CheckIfDiceAreMoving()
    {
        while(anyDieIsMoving){
            anyDieIsMoving = false;
            foreach (var die in _dice)
            {
                var dieRigidbody = die.GetComponent<Rigidbody>();
                if (!dieRigidbody.IsSleeping())
                {
                    anyDieIsMoving = true;
                    yield return null;
                }
            }
        }
    
        // Calculate score and do something with it...
    }
    
        3
  •  1
  •   Draco18s no longer trusts SE    6 年前

    除了其他两个答案所说的,我会改变 CheckIfDiceAreMoving() 以这种方式(使用Siusiulala的版本):

    while(anyDieIsMoving){
        anyDieIsMoving = false;
        foreach (var die in _dice)
        {
            var dieRigidbody = die.GetComponent<Rigidbody>();
            if (!dieRigidbody.IsSleeping())
            {
                anyDieIsMoving = true;
                break;
            }
        }
        yield return null;
    }
    

    一个模具不动,就冲出 for循环 因为它不再相关。原始代码将 for循环 暂停并返回 在同一索引处 稍后。毕竟,这是 while循环 我们要的是连体衣。