

One of the most frustrating and subtle bugs in Unity physics development is the Rigidbody Sleep Bug. This issue manifests when Rigidbody objects fail to wake up from sleep state under certain conditions, causing physics interactions to break, objects to pass through colliders, or movement systems to become unresponsive. Unlike obvious crashes or error messages, this bug often appears as inconsistent, hard-to-reproduce physics behavior that can undermine the core gameplay of any project using Unity’s physics engine.
In Unity, Rigidbody components have an automatic sleep system designed to optimize performance. When a Rigidbody’s velocity drops below a certain threshold (controlled by sleepThreshold in Unity 2019.3+ or Sleep Velocity in earlier versions) and no forces are acting upon it, Unity puts the Rigidbody to “sleep.” While sleeping, the physics engine skips calculations for that object, saving CPU cycles. The bug occurs when a sleeping Rigidbody should wake up due to external influences (collisions, forces, or manual activation) but fails to do so.
The console won’t show error messages—instead, you’ll experience symptoms like:
Understanding the underlying causes requires examining how Unity’s physics engine (PhysX by default) manages sleep states.
Unity’s default sleep threshold (0.005) works for most scenarios, but can cause problems with:
This is the most common technical cause. When you use:
Physics.Raycast()
or
Physics.CheckSphere()
These are query operations that don’t automatically wake up sleeping Rigidbodies. However, the actual physics simulation in FixedUpdate() does respect sleep states. This mismatch leads to situations where:
When you directly set a Rigidbody’s velocity:
rigidbody.velocity = new Vector3(10, 0, 0);
This doesn’t automatically wake up the Rigidbody if it’s sleeping. The velocity assignment happens, but the physics engine won’t apply it until the next time the Rigidbody is awake and processed.
Rigidbodies with interpolation enabled (especially “Interpolate” mode) can experience sleep bugs when:
Objects with multiple colliders forming a compound shape can experience partial sleep states where:
// Platform controller script
void Update() {
if (Input.GetKeyDown(KeyCode.Space)) {
// This doesn't wake up the Rigidbody!
platformRigidbody.velocity = Vector3.down * 5f;
}
}
// Some frames later, collision with floor might be missed
// because platform Rigidbody is still sleeping
void OnCollisionEnter(Collision collision) {
if (collision.gameObject.CompareTag("Player")) {
// Platform starts moving but might still be sleeping
MovePlatform();
}
}
void MovePlatform() {
// If platform was sleeping, this force might not apply immediately
platformRigidbody.AddForce(Vector3.right * 100f);
}
void FixedUpdate() {
// Check if object is above threshold
if (Physics.CheckSphere(transform.position, 1f)) {
// Activate connected Rigidbody
connectedBody.AddForce(Vector3.up * 50f);
// Bug: If connectedBody was sleeping, force might be delayed
}
}
The most reliable solution: explicitly wake up Rigidbodies before applying forces or changing velocity.
// BAD: May fail if Rigidbody is sleeping rigidbody.AddForce(Vector3.forward * 100f); // GOOD: Always wakes up the Rigidbody first rigidbody.WakeUp(); rigidbody.AddForce(Vector3.forward * 100f); // Also for velocity assignments rigidbody.WakeUp(); rigidbody.velocity = new Vector3(10, 0, 0);
Implement wrapper methods that handle sleep state automatically:
public static class PhysicsUtils {
public static void AddForceSafe(Rigidbody rb, Vector3 force, ForceMode mode = ForceMode.Force) {
if (rb != null && rb.gameObject.activeInHierarchy) {
rb.WakeUp();
rb.AddForce(force, mode);
}
}
public static void SetVelocitySafe(Rigidbody rb, Vector3 velocity) {
if (rb != null && rb.gameObject.activeInHierarchy) {
rb.WakeUp();
rb.velocity = velocity;
}
}
public static void MovePositionSafe(Rigidbody rb, Vector3 position) {
if (rb != null && rb.gameObject.activeInHierarchy) {
rb.WakeUp();
rb.MovePosition(position);
}
}
}
Adjust sleep thresholds based on object requirements:
void Start() {
// For precision objects that need to stay awake
if (requiresPreciseMovement) {
rigidbody.sleepThreshold = 0.001f; // Lower threshold
rigidbody.maxAngularVelocity = 7f; // Prevent premature sleep from rotation
}
// For heavy static objects that should sleep quickly
if (isHeavyStaticObject) {
rigidbody.sleepThreshold = 0.01f; // Higher threshold
}
}
When using physics queries that might interact with sleeping objects:
// Instead of just checking
if (Physics.Raycast(ray, out RaycastHit hit)) {
Rigidbody hitRb = hit.rigidbody;
if (hitRb != null) {
hitRb.WakeUp(); // Critical: Wake up before applying forces
hitRb.AddForce(Vector3.up * 50f);
}
}
For objects that must never pass through geometry:
void Start() {
rigidbody.collisionDetectionMode = CollisionDetectionMode.Continuous;
// Or for dynamic fast objects:
rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
}
Note: Continuous collision detection is more expensive but prevents tunneling through thin colliders when objects might be sleeping between frames.
For critical game systems, manually check and manage sleep states:
public class SleepAwareRigidbody : MonoBehaviour {
private Rigidbody rb;
private bool wasSleeping = false;
void Start() {
rb = GetComponent<Rigidbody>();
}
void FixedUpdate() {
bool isSleeping = rb.IsSleeping();
// Log state changes for debugging
if (wasSleeping && !isSleeping) {
Debug.Log($"{name} woke up at {Time.time}");
} else if (!wasSleeping && isSleeping) {
Debug.Log($"{name} fell asleep at {Time.time}");
}
// Force wake if critical object is sleeping
if (isSleeping && isCriticalObject) {
rb.WakeUp();
}
wasSleeping = isSleeping;
}
}
WakeUp() before AddForce(), velocity assignment, or MovePosition()[UnityTest]
public IEnumerator Test_Rigidbody_WakesUp_OnForceApplication() {
// Create test object
GameObject testObj = new GameObject("TestRigidbody");
Rigidbody rb = testObj.AddComponent<Rigidbody>();
testObj.AddComponent<BoxCollider>();
// Let it sleep
yield return new WaitForSeconds(1f);
Assert.IsTrue(rb.IsSleeping(), "Rigidbody should be sleeping");
// Apply force with WakeUp
rb.WakeUp();
rb.AddForce(Vector3.up * 10f);
// Should now be awake
yield return new WaitForFixedUpdate();
Assert.IsFalse(rb.IsSleeping(), "Rigidbody should be awake after force");
GameObject.Destroy(testObj);
}
Configure layers so critical objects don’t interact with sleep-prone objects:
// In Layer Collision Matrix (Edit > Project Settings > Physics): // - Layer "AlwaysAwake" interacts with everything // - Layer "SleepProne" doesn't interact with critical objects // This prevents sleep bugs from affecting critical gameplay
Create an editor visualization tool:
#if UNITY_EDITOR
[InitializeOnLoad]
public static class SleepStateVisualizer {
static SleepStateVisualizer() {
SceneView.duringSceneGui += OnSceneGUI;
}
static void OnSceneGUI(SceneView sceneView) {
foreach (var rb in GameObject.FindObjectsOfType<Rigidbody>()) {
if (rb.IsSleeping()) {
Handles.color = Color.red;
Handles.Label(rb.position, "SLEEPING");
Handles.DrawWireCube(rb.position, Vector3.one * 0.5f);
}
}
}
}
#endif
For objects where sleep is never appropriate:
void Start() {
rigidbody.sleepMode = RigidbodySleepMode.NeverSleep;
// Use judiciously - has performance implications
}
While preventing sleep bugs is important, indiscriminate use of WakeUp() or disabling sleep entirely can hurt performance:
Recommended approach: Profile your game’s physics performance with and without sleep optimizations. Use Unity’s Physics Profiler module to identify if sleep management is causing performance issues.
The Unity Rigidbody Sleep Bug represents a classic case of optimization (automatic sleep) conflicting with gameplay reliability. By understanding that physics queries don’t wake Rigidbodies, that manual velocity assignments bypass sleep checks, and that certain object configurations are prone to premature sleeping, developers can implement robust solutions.
The key takeaways are:
With these strategies, what begins as a frustrating, intermittent bug becomes a manageable aspect of physics-based development. By treating sleep state management as a first-class concern in your physics code, you’ll create more reliable, predictable interactions that form the foundation of polished gameplay experiences.