我目前正在Unity(C#)中复制粒子系统。我正在为每个粒子(由球体表示)添加物理,以允许它从位于原点的平面反弹。粒子会在重力作用下弹跳很多次。当弹跳变小时,球体开始穿过飞机直到最后坠落。重力将持续作用于粒子。将球体停在飞机顶部的正确方法是什么?
到目前为止,我已经包含了我的实现,但代码总是最终允许球体穿过平面。
检测:
public bool SpherePlaneCollisionDetection(Particle part)
{
Vector3 sphereCenter = part.position;
Vector3 planeCenter = Vector3.zero;
Vector3 normal = Vector3.up;
double radius = 0.5;
Vector3 dist1 = (sphereCenter - planeCenter);
float finalDist = Vector3.Dot (dist1, normal);
if (finalDist > radius) {
return false;
} else {
//Debug.Log ("COLLISION HAS OCCURED");
//Debug.Log ("POSITION: " + part.position);
//Debug.Log ("FINAL DIST: " + finalDist);
return true;
}
}
响应:
public void HandlePlaneCollision()
{
for (int i=0; i<Particles.Count; i++) {
//Particle p1temp = Particle[i];
Particle tempParticle = (Particle)Particles[i];
//Particle part = tempParticle.GetComponent<Particle>();
float dampning = 0.8f;
float bounce = -1f;
if(SpherePlaneCollisionDetection(tempParticle))
{
tempParticle.velocity.y *= (bounce*dampning);
tempParticle.velocity.x *= friction;
tempParticle.velocity.z *= friction;
Debug.Log(tempParticle.velocity.y);
Particles[i] = tempParticle;
}
}
}
非常感谢任何帮助。
答案 0 :(得分:2)
我不使用Unity,但之前我编码过物理模拟,这通常是因为:
抑制+浮动错误
是的,你正在挫败,所以如果你的物体在下降,那么它再次反弹(高度h0
)再次下降,然后再次反弹(高度h1<h0
)......所以它会以较低的速度振荡并且幅度较低但从不为零。
如果您使用的引擎/框架有一些性能调整来加速碰撞测试或者不能以更高的精度处理碰撞测试然后振荡那么它可能会错过边界命中,特别是只有平面边界而不是体积或者命中接近边界的顶点。
你可以通过消除振幅较低的振荡来避免这种,如我的评论所述:
if (|speed|<some_minimal_safe_speed)
然后将其设置为零以停止弹跳更好的是left just surface tangent speed part而不是零
错误的边界定义
一些边界碰撞测试系统要求以特定方式定义边界对象,如:
因此请在文档中检查并在需要时进行更正
采样率与模拟速度
您在某些时间间隔内对物体位置,速度,状态......进行采样。在碰撞检测时间内,您的物体通常已经在边界表面之下/之后但通常不完全(取决于速度和时间间隔)。当speed*time_interval
足够高时,对象被检测为碰撞,因此其速度在表面上是镜像并且被阻尼。
但是由于下一次迭代中的阻尼,位置仍然在边界之后,所以在迭代之后它被处理为正常的边界命中并以错误的方式反弹。这种情况发生在较高的速度而不是较低的速度......您可以通过将位置设置为曲面点击(如@Imapler注释)和/或+表面上方的某些增量来阻止此