The sleep function of the rigidbody

I’m working on a project where a rigid ball is hitting multiple rigid castles made of small rigid bodies.
But I had a problem with sleeping and waking up rigid bodies.

Here is my problem:

  • My rigid-body sleep function only works for the first object that is instantiated. For later instantiated objects, the sleeping rigidbody will still move.

Here are my codes:

  • This code is placed on each of the little rigid bodies that make up the castle

     private void Start()
         Rigidbody rb = this.gameObject.GetComponent<Rigidbody>();
         if (rb != null)

  • This code is placed on Main Camera

     void StartLevel()
         if(castle != null)
         GameObject[] gos = GameObject.FindGameObjectsWithTag("Projectile");
         foreach(GameObject pTemp in gos)
         castle = Instantiate<GameObject>(castles[level]);
         castle.transform.position = castlePos;
         shotsTaken = 0;

There is a complicated issue at work here. My guess is that it’s related to how Unity handles transform updates. When you do

transform.position = something;

Unity doesn’t immediately update the entire object (like informing the colliders about the updated position). Instead, all transforms that have been changed in a frame will be collected, and their updates will be handled at the end of the frame. This way, if you change the position of an object twice in a row, or the position and the rotation, Unity won’t be recalculating everything twice, but only once.

What also happens at the end of a frame is Start, where you send your Rigidbody to sleep. It seems that Start comes first, and the transform updates after, meaning that the Rigidbodies are moved after they’re send to sleep. My guess is that that wakes them up again.

There is a simple fix that worked for me while reproducing this: Set the position in the Instantiate call.
Instead of

castle = Instantiate<GameObject>(castles[level]);
castle.transform.position = castlePos;


castle = Instantiate<GameObject>(castles[level], castlePos, Quaternion.identity);

This will apply the position right away, so the Sleep() call will definitely come afterwards.

Also, you can omit the <GameObject> part:

castle = Instantiate(castles[level], castlePos, Quaternion.identity);