Short of makinga ll bodies in a scene static is it possible to stop physics updates from happening without disabling time altogether?
Well you can set a Rigidbody
’s Is Kinematic
property to true
to stop its automatic world interaction.
There’s many cases in which that would not suffice, but perhaps in your case it’s enough.
Whenever you want to ‘stop motion’, you will need to cycle all relevant scene objects and their Rigidbodies, and set their IsKinematic
attribute to true
.
I think it is possible to set the global Physics.sleepVelocity and Physics.sleepAngularVelocity to very high. this way your rigidbodies will fall asleep ignoring the system. But in order to get them back, you need to Awake all your rigidbodies I guess after setting the sleep parameters back.
There are many ways to make an object static, the following are in my opinion the best:
- Rigidbody.Sleep(). This would definitely be the cleanest and simplest.
- Destroy the rigidbody component. When you want the objects to no longer be static add the Rigidbody component back.
Roamcel’s method doesn’t actually help performance, since you would making the objects kinematic will make it have to check for collisions regardless.
Martijn Hendriks’s method is fine but not the greatest. If you were to go down this path you would be better off setting these settings indiviudally. Rigidbody.sleepAngularVelocity and Rigidbody.sleepVelocity.
In some cases it might be sufficient to deactivate the rigidBody containing GameObject, provided you don't have any renderers or other components attached (this is my case, i have rigidBodies separated from actors and actors being "springed" to their rigidBodies for smoothing lag ) and all rigidBodies are parented to single gameObject so all i have to do is call SetActiveRecursively and all my physics stops
– AyersFor me the problem was a little more complex :
I had to pause a Gameobject’s Rigidbody and resume it in order to have an animated pause menu.
So, to fix it I proceed as follows :
- Save your
rigidbody.velocity
(instance) - Pause the rigidbody using
rigidbody.Sleep()
orrigidbody.isKinematic = true
(both on your rigidbody instance) - Wait until the player wants to resume…
- Resume the rigidbody using
rigidbody.WakeUp()
orrigidbody.isKinematic = false
(both on your rigidbody instance) - Set up your
rigidbody.velocity
(instance) with the one you saved at the first step
Here is an exemple :
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
private Vector3 velocity;
void Update () {
if (Input.GetKeyDown(KeyCode.Space)) {
// Pause the game when the player hit the Space key
velocity = rigidbody.velocity;
rigidbody.isKinematic = true;
} else if (Input.GetKeyUp(KeyCode.Space)) {
// Resume the game when the player release the Space key
rigidbody.isKinematic = false;
rigidbody.velocity = velocity;
}
}
}
Uhm, isn't that exactly what chillypacman used as solution? Have you read his comment on the selected answer? Also you do not save the angularVelocity of the rigidbody. If your objects aren't rotated by forces that might be not important, but for a general solution it should be included.
– EisenI would argue that this answer is more complete. As just making an object kinematic is not sufficient to enable an object to be reactivated retaining the previous state of movement.
– AshurbanipalAs of Unity 2017+, this should be marked as the better correct answer now. Thanks! (more info on Physics.autoSimulation -- https://docs.unity3d.com/ScriptReference/Physics-autoSimulation.html)
– ShippingFor those who what to pause 2D engine programmatically without changing properties RigidBody2D
and whatsoever, just use:
Physics2D.autoSimulation = false;// to pause
and
Physics2D.autoSimulation = true;// to resume.
In my case, Sleep()
was not enough as the objects can start moving even if not set to Wake()
yet. What worked for me is saving the Rigidbody velocity and angular velocity and then setting the freeze constraints. That way you don’t need to change anything else in the program.
Here is the code:
void Animate(bool on)
{
if (on)
{
rb.constraints = RigidbodyConstraints.None;
// Restore velocities
rb.velocity = savedVelocity;
rb.angularVelocity = savedAngularVelocity;
}
else
{
//Save current velocities
savedVelocity = rb.velocity;
savedAngularVelocity = rb.angularVelocity;
rb.constraints = RigidbodyConstraints.FreezeAll;
}
}
© 2022 - 2024 — McMap. All rights reserved.
Yeah I ended up doing as you suggested and saving the velocities of all rigid bodies so I could restore them after making them unkinematic.. pity ther eisn't a more elegant solution (i.e. halting physics by timestep).
– RegularlyHave you added the comment to the wrong answer, or am I not understanding you correctly?
– QuadragesimaI was justing adding to what you were saying, setting a rigidbody to kinematic doesn't only freeze dynamic bodies but also takes away their velocities so I had to save them then restore them on making them dynamic again...
– RegularlyOk, my misunderstanding then
– QuadragesimaI'm happy that you sorted it out, Jabber. Well done.
– Derangement