Скорость твердого тела иногда равна нулю, когда твердое тело движется - PullRequest
0 голосов
/ 20 февраля 2019

Я пытаюсь добавить звук к моему объекту, который может быть удален, и просто имею простое выражение if для проверки, движется ли объект, который может быть перемещен.Концепция довольно проста: если объект движется, звук должен воспроизводиться, а когда он не движется, он не должен.Проблема, однако, в том, что когда я отлаживаю значение, появляется 0 каждые 5 кадров или около того.Это заставляет звук работать непоследовательно.Сценарий, который у меня есть, очень прост, и я попытался перейти на исправление, но это не сработало.Я где-то читал, что физические вычисления выполняются в fixedUpdate.

public class PushableObject : MonoBehaviour
{
    Rigidbody rb;
    AudioSource audioS;

    bool rbIsMoving = false;

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();
        audioS = GetComponent<AudioSource>();
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        if (rb.velocity == Vector3.zero)
        {
            Debug.Log("Not moving");
            audioS.volume = 0f;
        }
        else
        {
            Debug.Log("Moving");
            audioS.volume = 0.1f;
        }
    }
}

Редактировать: Я только что понял, что если игрок толкает толкаемый объект в стену, звук все еще играет, поэтому я думаю,Я должен изменить способ, чтобы определить, движется ли объект или нет.

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Это происходит из-за плавающей запятой одинарной точности .

. Вы никогда не должны (должны) сравнивать два float значения напрямую, поскольку они могут быть логически равными (например, 1 = 5*0.2), но дляна компьютере они могут отличаться маленьким «эпсилоном»

Так что Unity решает, что Vector3 просто использует только точность 0.00001 для равенства для ==


Вместо этого используйте Mathf.Approximately, в котором вместо этого используется Epsilon .


Чем проще, чем сравнивать каждый компонент rb.velocity с0 То, что вы на самом деле хотите, это rb.velocity.magnitude, которая фактически является общей скоростью.

if (Mathf.Approximately(rb.velocity.magnitude, 0))

Обновление

Либо сохраните последнюю позицию и сравните ее с текущей, используя Vector3.Distance , либо снова с Mathf.Approximately

private Vector3 lastPosition;

private void LateUpdate()
{
    if(Mathf.Approximately(Vector3.Distance(lastPosition, transform.position), 0))
    {
        //...
    }
    else
    {
        //...
        lastPosition = transform.positiom;
    }
}

Или с пользовательским порогом

if(Vector3.Distance(lastPosition, transform.position) <= someThreshold)

или на этот раз вы действительно можете использовать ==, если порог 0.00001 - это то, что вы хотите

if(lastPosition == transform.position)
0 голосов
/ 20 февраля 2019

Вы можете проверить, не спит ли RigidBody:

if (!rb.IsSleeping()
{
//it's moving
}
else
{
//it's not
}

Или проверить, сместилась ли позиция преобразования с последнего кадра:

Vector3 lastposition;
Gameobject go = somegameobject; 

function Update()
{
    if (lastposition == go.transform.position)
    {
     //not moving
    }
    else
    {
     //moving
    }
    lastposition = go.transform.position;
}
...