user2720
user2720

Reputation: 73

Why do objects get stuck together in Unity?

I have a 2D scene that consists of 4 sprites, each with a box collider.

Boxes

I then have a prefab that is simply a sprite of a circle with a 2D circle collider.

Finally I have a script named Atmosphere attached to my main camera that will fill the box with lots of instances of the prefab and give them a velocity in a random direction.

using 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;
        }
    }
}

For a while the dots bounce around against each other and the edges of the box.

Happy bouncing

But after a while they eventually get stuck to the edges of the box.

Sticky balls

Both the box and balls and the box walls have the same physics material

Physics material

Which has zero friction and a bounciness of 1.

Physics material settings

Why do they stick to the walls, and how can I stop it from happening?

Download Unity 3D demo

UPDATE If I drop a single molecule into the box with the following script attached it gets stuck to the wall immediately.

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

Upvotes: 1

Views: 4215

Answers (3)

AliSafari186
AliSafari186

Reputation: 113

colliders may be stuck in each other for the reason of low contact offset, go to edit-project settings-physics2d and increase the default contact offset a little bit, 0.12 for example, it was work for me.

cheers

Upvotes: 0

user2720
user2720

Reputation: 73

Unity3D has a velocity threshold. Objects with a velocity below this threshold won't bounce etc.

The solution is to go to Edit > Project Settings > Physics 2D and to set the Velocity Threshold lower.

Upvotes: 2

Jon Koelzer
Jon Koelzer

Reputation: 350

EDIT - The real solution:

So I was doing some reading on integration techniques and it hit me: The energy you're losing is quite likely coming from numerical inaccuracies stemming from several approximation techniques compounded.

I'm guessing the continuous collision detection algorithm is mostly to blame, floating-point error accumulation, but probably also from numerical integration techniques.

What you're trying to achieve is elastic collision, which means that it satisfies conservation of energy as well as momentum. The trick is going to be for you to add a script to every object that preserves the energy of the system by adding error-correcting velocity over time. Whether you actually use the energy route or not is up to you, there are a number of ways to track and modify the energy resulting in a change of velocity. Momentum would be the would be the easiest to track in my opinion. What you're trying to achieve is elastic collision, which means that it satisfies conservation i.e.

  1. Make a component that preserves the scalar quantity of kinetic energy or momentum (it'll probably produce the same results)

  2. When you initialize all the particles with a velocity, make sure to save the starting momentum in the particle's script. I would save the scalar quantity for simplicity, so just use the length of velocity

  3. Every frame, in the update event check the velocity of the rigid body. Find the change in momentum or change in energy and add the -difference and apply it to the object.

I doubt you'll have to work on collision events as well, especially if you use the exact same mass for every object. Here's a link with an example where someone corrected unity's friction-less physics using conservation of energy https://answers.unity.com/questions/168393/frictionless-physics.html

Upvotes: 0

Related Questions