为什么对象在 Unity 中会卡在一起?
Why do objects get stuck together in Unity?
我有一个包含 4 个精灵的 2D 场景,每个精灵都有一个盒子碰撞器。
然后我有一个预制件,它只是一个带有 2D 圆形碰撞器的圆形精灵。
最后,我有一个名为 Atmosphere 的脚本附加到我的主摄像头,它将用大量预制件实例填充盒子,并为它们提供随机方向的速度。
使用 UnityEngine;
public class Atmosphere : MonoBehaviour
{
public GameObject Molecule;
void Start()
{
float x = -4.5f;
while (x < 4.5f)
{
float y = -4.5f;
while (y < 4.5f)
{
var inst = GameObject.Instantiate(Molecule);
inst.transform.position = new Vector3(x, y, 0);
var rb = inst.GetComponent<Rigidbody2D>();
float xForce = Random.value * 2f - 1f;
float yForce = Random.value * 2f - 1f;
rb.AddForce(new Vector2(xForce, yForce) * 100f);
y += 0.5f;
}
x += 0.5f;
}
}
}
有一段时间,这些点相互弹跳,并在盒子的边缘弹跳。
但过了一会儿,它们最终卡在了盒子的边缘。
盒子和球以及盒子壁具有相同的物理特性material
摩擦力为零,弹性为 1。
为什么它们会粘在墙上,我怎样才能阻止它发生?
更新
如果我将一个分子放入附有以下脚本的盒子中,它会立即粘在墙上。
[RequireComponent(typeof(Rigidbody2D))]
public class Molecule : MonoBehaviour
{
Rigidbody2D RigidBody2D;
void Start()
{
transform.position = new Vector3(0, 1, 0);
RigidBody2D = GetComponent<Rigidbody2D>();
float xForce = Random.value * 2f - 1f;
float yForce = Random.value * 2f - 1f;
RigidBody2D.AddForce(new Vector2(-.25f, -0.25f) * 100f);
}
}
编辑 - 真正的解决方案:
所以我正在阅读一些关于积分技术的资料,这让我震惊:你失去的能量很可能来自于多种近似技术复合产生的数值不准确。
我猜主要是连续碰撞检测算法的罪魁祸首,浮点误差累积,但也可能来自数值积分技术。
你要实现的是弹性碰撞,也就是说既满足动量守恒又满足能量守恒。诀窍是为每个对象添加一个脚本,通过随时间增加纠错速度来保持系统的能量。您是否实际使用能量路线取决于您,有多种方法可以跟踪和修改导致速度变化的能量。在我看来,动量将是最容易追踪的。您要实现的是弹性碰撞,这意味着它满足守恒
即
制作一个保留动能或动量标量的组件(它可能会产生相同的结果)
当您用速度初始化所有粒子时,请确保在粒子脚本中保存起始动量。为了简单起见,我会保留标量,所以只需使用速度的长度
每一帧,在更新事件中检查刚体的速度。找到动量的变化或能量的变化,并添加 -difference 并将其应用于对象。
我怀疑您是否也必须处理碰撞事件,尤其是当您对每个对象使用完全相同的质量时。这是一个 link 示例,其中有人使用能量守恒 https://answers.unity.com/questions/168393/frictionless-physics.html
修正了 unity 的无摩擦物理学
Unity3D 有一个速度阈值。速度低于此阈值的物体不会反弹等
解决方案是转至 编辑 > 项目设置 > 物理 2D 并将速度阈值设置得较低。
碰撞器可能由于低接触偏移而相互卡住,转到编辑-项目设置-physics2d 并稍微增加默认接触偏移,例如 0.12,这对我有用。
干杯
我有一个包含 4 个精灵的 2D 场景,每个精灵都有一个盒子碰撞器。
然后我有一个预制件,它只是一个带有 2D 圆形碰撞器的圆形精灵。
最后,我有一个名为 Atmosphere 的脚本附加到我的主摄像头,它将用大量预制件实例填充盒子,并为它们提供随机方向的速度。
使用 UnityEngine;
public class Atmosphere : MonoBehaviour
{
public GameObject Molecule;
void Start()
{
float x = -4.5f;
while (x < 4.5f)
{
float y = -4.5f;
while (y < 4.5f)
{
var inst = GameObject.Instantiate(Molecule);
inst.transform.position = new Vector3(x, y, 0);
var rb = inst.GetComponent<Rigidbody2D>();
float xForce = Random.value * 2f - 1f;
float yForce = Random.value * 2f - 1f;
rb.AddForce(new Vector2(xForce, yForce) * 100f);
y += 0.5f;
}
x += 0.5f;
}
}
}
有一段时间,这些点相互弹跳,并在盒子的边缘弹跳。
但过了一会儿,它们最终卡在了盒子的边缘。
盒子和球以及盒子壁具有相同的物理特性material
摩擦力为零,弹性为 1。
为什么它们会粘在墙上,我怎样才能阻止它发生?
更新 如果我将一个分子放入附有以下脚本的盒子中,它会立即粘在墙上。
[RequireComponent(typeof(Rigidbody2D))]
public class Molecule : MonoBehaviour
{
Rigidbody2D RigidBody2D;
void Start()
{
transform.position = new Vector3(0, 1, 0);
RigidBody2D = GetComponent<Rigidbody2D>();
float xForce = Random.value * 2f - 1f;
float yForce = Random.value * 2f - 1f;
RigidBody2D.AddForce(new Vector2(-.25f, -0.25f) * 100f);
}
}
编辑 - 真正的解决方案:
所以我正在阅读一些关于积分技术的资料,这让我震惊:你失去的能量很可能来自于多种近似技术复合产生的数值不准确。
我猜主要是连续碰撞检测算法的罪魁祸首,浮点误差累积,但也可能来自数值积分技术。
你要实现的是弹性碰撞,也就是说既满足动量守恒又满足能量守恒。诀窍是为每个对象添加一个脚本,通过随时间增加纠错速度来保持系统的能量。您是否实际使用能量路线取决于您,有多种方法可以跟踪和修改导致速度变化的能量。在我看来,动量将是最容易追踪的。您要实现的是弹性碰撞,这意味着它满足守恒 即
制作一个保留动能或动量标量的组件(它可能会产生相同的结果)
当您用速度初始化所有粒子时,请确保在粒子脚本中保存起始动量。为了简单起见,我会保留标量,所以只需使用速度的长度
每一帧,在更新事件中检查刚体的速度。找到动量的变化或能量的变化,并添加 -difference 并将其应用于对象。
我怀疑您是否也必须处理碰撞事件,尤其是当您对每个对象使用完全相同的质量时。这是一个 link 示例,其中有人使用能量守恒 https://answers.unity.com/questions/168393/frictionless-physics.html
修正了 unity 的无摩擦物理学Unity3D 有一个速度阈值。速度低于此阈值的物体不会反弹等
解决方案是转至 编辑 > 项目设置 > 物理 2D 并将速度阈值设置得较低。
碰撞器可能由于低接触偏移而相互卡住,转到编辑-项目设置-physics2d 并稍微增加默认接触偏移,例如 0.12,这对我有用。
干杯