刚体运动时,刚体速度有时为零

时间:2019-02-20 16:09:39

标签: c# unity3d velocity rigid-bodies

我正在尝试将声音添加到可推动对象中,并且只有一个简单的if语句来检查可推动对象是否在移动。这个概念非常简单,如果对象正在移动,则声音应该播放,而当对象不移动时,声音不应该播放。但是问题是,当我调试该值时,每5帧左右就有一个0。这会导致声音不一致地工作。我拥有的脚本非常简单,我尝试将其更改为fixedupdate,但没有用。我读过某个地方,物理计算是在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;
        }
    }
}

编辑:我刚刚发现,如果玩家将可推动对象推入墙壁,声音仍在播放,因此,我认为我也必须改变确定对象是否在移动的方式。

3 个答案:

答案 0 :(得分:3)

发生这种情况的原因是single precision floating point

您绝对不能(应该)直接比较两个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))

更新

或者存储最后一个位置,并使用Mathf.Approximately再次使用Vector3.Distance将其与当前位置比较

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)

答案 1 :(得分:2)

您可以检查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;
}

答案 2 :(得分:0)

您可以使用Transform.hasChanged来检查玩家位置在上次更新时是否已更改

        if (!this.transform.hasChanged)
        {
            print("Player is not moving");
        }
        transform.hasChanged = false;