为啥物体在 Unity 中会粘在一起?

Posted

技术标签:

【中文标题】为啥物体在 Unity 中会粘在一起?【英文标题】:Why do objects get stuck together in Unity?为什么物体在 Unity 中会粘在一起? 【发布时间】:2019-05-10 00:11:00 【问题描述】:

我有一个由 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;
        
    

有一段时间,这些点相互反弹,并在盒子的边缘反弹。

但一段时间后,它们最终会卡在盒子的边缘。

盒子和球以及盒子壁都具有相同的物理材质

摩擦力为零,弹力为 1。

为什么它们会粘在墙上,我该如何阻止它发生?

Download Unity 3D demo

更新 如果我将一个分子放入附有以下脚本的盒子中,它会立即粘在墙上。

[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);
    

【问题讨论】:

你试过在墙上加一点Bounciness吗? @Morasiu 他们共享相同的物理材料。 【参考方案1】:

Unity3D 有一个速度阈值。速度低于此阈值的物体不会反弹等。

解决方案是转到 Edit > Project Settings > Physics 2D 并将 Velocity Threshold 设置得更低。

【讨论】:

【参考方案2】:

编辑 - 真正的解决方案:

所以我读了一些关于积分技术的书,突然发现:你失去的能量很可能是由于几种近似技术的复合导致的数值不准确。

我猜测连续碰撞检测算法主要是罪魁祸首,浮点误差累积,但也可能来自数值积分技术。

您要实现的是弹性碰撞,这意味着它满足能量守恒和动量守恒。诀窍是为每个对象添加一个脚本,通过随着时间的推移添加纠错速度来保留系统的能量。是否实际使用能量路线取决于您,有多种方法可以跟踪和修改能量,从而导致速度变化。在我看来,动量将是最容易追踪的。您要实现的是弹性碰撞,这意味着它满足守恒 即

    制作一个保持动能或动量标量的组件(它可能会产生相同的结果)

    使用速度初始化所有粒子时,请确保在粒子脚本中保存起始动量。为了简单起见,我会保存标量,所以只需使用速度的长度

    每一帧,在更新事件中检查刚体的速度。找出动量的变化或能量的变化,加上 - 差并将其应用于对象。

我怀疑您是否也必须处理碰撞事件,特别是如果您对每个对象使用完全相同的质量。这是一个示例链接,其中有人使用能量守恒https://answers.unity.com/questions/168393/frictionless-physics.html

纠正了统一的无摩擦物理

【讨论】:

感谢您的帮助!不幸的是,这些都没有帮助。我没有尝试圆形,因为我想要一个正方形。你还有其他建议吗?这似乎是一个错误。 你能在屏幕上的某处获得调试输出或标签吗?尝试使用具有起始速度的恰好 1 个粒子进行模拟,并在每帧流式传输速度的大小,以便我们可以查看是否以及何时发生能量损失。如果速度下降,我们可以肯定地说这是 CCD 中的错误。一个想法,如果他们使用 GJK 和 EPA 算法,我们知道这实际上是一个近似值,并且可能导致它。如果它确实有效,问题出在圆圈上,我们可以尝试从那里开始(甚至可能是一个黑客,你可以手动修复速度的大小) 我不能保存每个分子的能量,因为让它们以不同的速度移动是目的的一部分。我现在能够用单个分子进行复制,请参阅更新后的问题。 我昨晚实际上也更新了我的答案,在能量保存方面,无论起始速度如何,您都应该能够通过监测动能与势能来保存能量 - 请参阅随附的链接统一脚本中的示例实现。由于弹性碰撞会保留能量,因此起始速度差异应该不是问题。我鼓励您查看一些弹性碰撞示例问题以获得一些灵感。 是的,这当然是一个有趣的问题。我今天下课后看看,今晚我会回复你【参考方案3】:

碰撞器可能因为接触偏移量低而相互卡住,进入edit-project settings-physics2d并稍微增加默认接触偏移量,例如0.12,这对我有用。

干杯

【讨论】:

以上是关于为啥物体在 Unity 中会粘在一起?的主要内容,如果未能解决你的问题,请参考以下文章

unity,C#,如下,为啥物体不动?还需要加上啥吗?

unity UGUI为啥在父物体绑定拖拽脚本,子物体也能拖拽?

unity3d我想把物体拖拽到脚本里为啥不行呢?如图

unity中为啥鼠标点击后就看不见鼠标了

unity为啥射线检测不到ui

Unity3D动画播放完毕后,为啥物体状体会默认回到之前的状态