我正在尝试将声音添加到可推动对象中,并且只有一个简单的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;
}
}
}
编辑:我刚刚发现,如果玩家将可推动对象推入墙壁,声音仍在播放,因此,我认为我也必须改变确定对象是否在移动的方式。
答案 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;