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

时间:2018-08-02 02:00:49

标签: c# unity3d coroutine

这似乎是一个简单的问题,但我很难解决。我正在滚动一些骰子(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 个答案:

答案 0 :(得分:2)

您必须使RollDice为协程函数,然后才能屈服或等待CheckIfDiceAreMoving函数以yield return返回。更好的是,将if (!dieRigidbody.IsSleeping())变成while (!dieRigidbody.IsSleeping()),以使CheckIfDiceAreMoving功能在所有骰子停止移动之前不会退出。另外,请检查Update函数中的输入,而不要使用用于移动FixedUpdate的{​​{1}}。

这是分解代码:

Rigidbody

答案 1 :(得分:1)

RollDice()中,它会在获得 anyDieIsMoving 状态之前计算分数。我想您显示将计算分数移至协程。

var contacts  = {

   
  1: {
    first: "Mike",
    last: "Johnson",    
    email:"mjohnson@gmail.com",
    phone:"(203) 567-9055",
    status:"1"
 },
  2: {
    first: "John",
    last: "Dunn",    
    email:"jdunn@gmail.com",
    phone:"(319) 451-7889",
    status:"1"
 },
  3: {
    first: "Lisa",
    last: "Morgan",    
    email:"lmorgan@gmail.com",
    phone:"(508) 233-8908",
    status:"1"
 },
  4: {
    first: "Dave",
    last: "Hart",    
    email:"dhart@gmail.com",
    phone:"(509) 874-9411",
    status:"1"
 }
};

var frmKey = 5;
if(contacts[frmKey]){
console.log(contacts[frmKey]);
 // If already exist in array then update object
}else{
  contacts[frmKey] = {first: "Lisa1",last: "Morgan1", email:"lmorgan1@gmail.com", phone:"(508) 233-8908", status:"1" };

  console.log("Added New Key::"+frmKey,contacts[frmKey]);

}

答案 2 :(得分:1)

除了其他两个答案所说的以外,我将以这种方式更改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循环