我正在尝试将声音添加到我的可推送对象中,并且只是有一个简单的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;
}
}
}
编辑:我刚刚发现,如果玩家将可推动的物体推入墙壁,声音仍在播放,因此我认为我必须改变方式,确定物体是否在移动。
这是因为single precision floating point。
你永远不应该(应该)直接比较两个float
值,因为它们在逻辑上可能是相等的(例如1 = 5*0.2
),但对于计算机,它们可能因小的“epsilon”而不同。
所以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)
你可以检查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;
}