Cubes above not falling

hi guys

having a strange problem. I have a stack of cubes being hit by a ball, its kind of like break out, but the other way round. The paddle is at the top hitting the blocks on the bottom. I’m trying to make it that when i hit the cube near the bottom the ones above fall down and explode. When the ball hits a cube mid way it explodes and disappears, but the cube above isnt falling for some reason, so there is a gap between the blocks. If i drag the cube out from the pile during run time, the stack behaves exactly how i want and fall and explode. It seems just when the ball destroys a block the one above it doesnt fall.

The funny thing is that if i change any setting on the rigidbody or collider, it falls immediately. Changing the mass by 1 makes it fall.

here is my code for the block:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CompartmentController : MonoBehaviour
{
    public GameObject compartmentExplodes;
    public AudioSource compartmentExplodesSound;
    public Collider physicsCollider;
    public MeshRenderer mesh;
    public Rigidbody rb;
    float maxSpeed = 0.5f; // units/sec.
    private bool smashedFromFall = false;
    private bool compartmentDestroyed = false;

    private bool hitGround = false;
    private bool hitByBall = false;
    private bool hitByCompartment = false;
    void Start()
    {
        Rigidbody rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        CheckBreakForce();
        DestroyCompartment();
    }

    public void CheckBreakForce()
    {
        Rigidbody rb = GetComponent<Rigidbody>();
        Vector3 vel = rb.velocity;
       
        if (vel.magnitude > maxSpeed)
        {
            print(vel);
            smashedFromFall = true;
        }
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == "Ball")
        {
            hitByBall = true;
        }

        if (collision.gameObject.tag == "Ground")
        {
            hitGround = true;
        }

        if (collision.gameObject.tag == "Compartment")
        {
            hitGround = true;
        }
    }

    public void DestroyCompartment()
    {
        if (smashedFromFall && hitGround || smashedFromFall && hitByCompartment || hitByBall)
        {
            if (!compartmentDestroyed)
            {
                smashedFromFall = false;
                hitByBall = false;
                compartmentExplodesSound.Play();
                physicsCollider.enabled = false;
                mesh.enabled = false;
                GameObject newBomb = Instantiate(compartmentExplodes, transform.position, transform.rotation);
            }

            compartmentDestroyed = true;
           
            Destroy(gameObject, 3f);
        }
    }
}

And for my ball:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnergyBombController : MonoBehaviour
{
    public Rigidbody rb;

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag != "Baton" || collision.gameObject.tag != "Barrier")
        {
            rb.AddForce(new Vector2(0, 2));
        }

        if (collision.gameObject.tag == "Barrier")
        {
            rb.AddForce(new Vector2(0, -2));
        }
       
    }


}

It’s probably falling asleep. Check the docs on RB for how to prevent that.

1 Like

Hi Kurt,

I put rb.wakeup() in my Update function. But now the blocks are moving. and my tower collapses after time. I tried putting a physics material on with static but this doesnt help. I also tried adding drag, but then that effects them when they fall, though it didnt really stop them “slipping”. Any suggestions?

The thing i dont get is that if i put them all on a platform and disable it they fall. seems its only when the ball destroys one, the above dont fall.

The more physics objects are in contact with each other, the harder the physics solver has to work to figure it out.

There’s a limit (adjustable by you) to how much effort the solver will take.

Complexity beyond that limit generally means that the physics will not become quiescent and will continue jostling and wiggling indefinitely.

That’s why sleeping below a certain threshold of movement is useful. This code demos it pretty nicely:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// @kurtdekker
//
// beyond a certain number of stacked contacting rigidbodies,
// the solver can't get them quiescent enough to sleep them.
//
// make an empty scene and drop this on a GameObject.

public class PhysicsStack : MonoBehaviour
{
    [Header( "Adjust to see if it can sleep.")]
    public int count;

    void Reset()
    {
        count = 15;
    }

    void Start ()
    {
        // low down in front-ish of the default camera
        // beyond about 20 you gotta go even further +Z
        var pos = new Vector3( 0, -8, 10);

        for (int i = 0; i < count; i++)
        {
            var cube = GameObject.CreatePrimitive( PrimitiveType.Cube);
            cube.transform.position = pos;

            // bottom cube has no Rigidbody, it is the fixed base
            if (i > 0)
            {
                // enable this...
                //var rb =

                cube.AddComponent<Rigidbody>();

                // ... and try tinkering with sleep threshold
//                rb.sleepThreshold = ...
            }

            pos += Vector3.up * 1.05f;
        }
    }
}