- Home /
How to check if an object has stopped moving?
Hey guys,
I have an object, with a rigidbody on it. I have it as the player. I want to be able to check exactly when the object has stopped moving. By this I don't mean completely stop moving because that would take a very long time and it isn't precise.
How would I go about checking if the object has almost stopped moving completely?
Also, how would I make it that when the rigidbody has almost completely stopped, the script then forcibly completely freezes the character?
Answer by AndyMartin458 · Jul 02, 2014 at 04:59 PM
I kind of took this question to heart and coded it up for you. You essentially want to store a few of the previous positions of the object and check if the distance between any of those positions is really small. Hopefully the comments and the code explain it better than me.
//Set this to the transform you want to check
private Transform objectTransfom;
private float noMovementThreshold = 0.0001f;
private const int noMovementFrames = 3;
Vector3[] previousLocations = new Vector3[noMovementFrames];
private bool isMoving;
//Let other scripts see if the object is moving
public bool IsMoving
{
get{ return isMoving; }
}
void Awake()
{
//For good measure, set the previous locations
for(int i = 0; i < previousLocations.Length; i++)
{
previousLocations[i] = Vector3.zero;
}
}
void Update()
{
//Store the newest vector at the end of the list of vectors
for(int i = 0; i < previousLocations.Length - 1; i++)
{
previousLocations[i] = previousLocations[i+1];
}
previousLocations[previousLocations.Length - 1] = objectTransfom.position;
//Check the distances between the points in your previous locations
//If for the past several updates, there are no movements smaller than the threshold,
//you can most likely assume that the object is not moving
for(int i = 0; i < previousLocations.Length - 1; i++)
{
if(Vector3.Distance(previousLocations[i], previousLocations[i + 1]) >= noMovementThreshold)
{
//The minimum movement has been detected between frames
isMoving = true;
break;
}
else
{
isMoving = false;
}
}
}
That is a way overly complicated piece of code when a simple three lines like Lyle23 showed would do.
You compare 9 floats each frame, when only one is necessary, and then 9 more distance checks when only one is necessary.
Thanks for this awesome script! This is really accurate, and even though it's complex it works with all the bells and whistles. :)
I like this. @fafase, the code is good if the GameOject does not have rigidbody attached to it or if it does. Lyle23's answers requires the GameObject to have rigidbody and the object to be moved with addforce/velocity for it to work.
Really like this code. Easy to implement and execute. Though there is a problem I found with it:
for(int i = 0; i < previousLocations.Length - 1; i++) { if(Vector3.Distance(previousLocations[i], previousLocations[i + 1]) >= no$$anonymous$$ovementThreshold)
This loop will cause the script to check for the index[0] and index[1] from the first updating frame. However since this line of code:
previousLocations[previousLocations.Length - 1] = objectTransfom.position;
stored our newest position at the end of the array i.e index[2], the script will say is$$anonymous$$oving = false even if the object is still moving. This is due to the script checking the index 0 and 1. They are both still have the value of 0 and haven't updated yet. Only the last index is updating during the first updating frame. $$anonymous$$y suggestion is to drop that second loop and have the update checking
if(Vector3.Distance(previousLocations[0], previousLocations[0 + 2]) >= no$$anonymous$$ovementThresho
ins$$anonymous$$d. This will eli$$anonymous$$ate any unintentional error in the inspector that I have encountered. Cheers.
Answer by Lylek · Jul 03, 2014 at 12:24 AM
float speed;
void Update () {
speed = rigidbody.velocity.magnitude;
if(speed < 0.5) {
gameObject.rigidbody.velocity = new Vector3(0, 0, 0);
//Or
gameObject.rigidbody.constraints = RigidbodyConstraints.FreezeAll;
}
}
This is a great script but since I'm launching the player upwards, when he begins his descent down it freezes him at the peak of the arc.
The "RigidbodyConstraints.FreezeAll" really helped though :)
This is the better method. You could improve it slightly by checking against velocity.sqr$$anonymous$$agnitude ins$$anonymous$$d.
Hi, if i want to achieve scale the gameobject over time and **scaling if the gameobject hit obstracles**am i correct? why unity show me Parsing error??
// to scale the gameobject over time // stop scaling if the gameobject hit obstracles
using UnityEngine; using System.Collections; using UnityEngine.UI;
public class ScaleObject : $$anonymous$$onoBehaviour { public float speed, growth; public Vector2 direction;
// Update is called once per frame
void Update () {
speed = rigidbody.velocity.direction;
if (speed < 0.02) {
Transform.localScale -= new Vector3 (growth* Time.deltaTime, growth* Time.deltaTime, 0);
}else{
transform.localScale += new Vector3 (growth* Time.deltaTime, growth* Time.deltaTime, 0);
transform.Translate (direction * speed * Time.deltaTime);
}
}
@liowweiting , Parsing error, more often than not, is forgotten/missing brackets. It means unity expects one thing and youre saying something different. Also... this should be its own question, but since its redundant to post it again... you need another } at the end.
i would solve it the same way. Easy and clean. The freezeall isnt that nice though since you would need to unfreeze right the next/same frame.
Answer by pumpkinszwan · Jul 03, 2014 at 12:29 AM
In my game I use Rigidbody's sleep property. Once a rigidbody is not being acted upon it will sleep, and this indicates it is not moving:
http://docs.unity3d.com/ScriptReference/Rigidbody.Sleep.html
This works for me. Because there is no hint in the link how to get the status this should help: https://docs.unity3d.com/ScriptReference/Rigidbody.IsSleeping.html
Fantastic the only answer that really worked for me I try all the others first but could not get them working quite right ....Thank you
Answer by BranchOffGameStudio · Apr 23, 2018 at 11:30 PM
A little late to the party here. Andy's answer works well for checking using transform. Lylek's answer works well for gameobjects with rigid bodies. I have another solution similar to Andy's for those who would like a smaller code example.
private bool isBeingMoved;
private Vector3 priorFrameTransform;
public Transform lens;
bool IsBeingMoved {
get { return this.isBeingMoved; }
set {
if (this.isBeingMoved && !value)
// Transformation has stopped
this.isBeingMoved = value;
}
}
// Use this for initialization
void Start () {
IsBeingMoved = false;
priorFrameTransform = transform.position;
}
// Update is called once per frame
void Update () {
if (Vector3.Distance(transform.position, priorFrameTransform) > 0.01f ) {
IsBeingMoved = true;
} else {
if (IsBeingMoved)
IsBeingMoved = false;
}
priorFrameTransform = transform.position;
}
Answer by WaqasHaiderDev · Aug 31, 2020 at 09:21 AM
May be this one line of code solves your issue. This works in my case.
I also tried rigidbody.IsSleeping() in my case but it was not returning true even when vehicle was nearly stopped. Maybe because the vehicle was always moving a very little amount let say 0.0001 units to and from because its engine were started so in my case, this solved the issue.
if(rigidbody.transform.InverseTransformDirection(rigidbody.velocity).z < 0.1f && rigidbody.transform.InverseTransformDirection(rigidbody.velocity).z > -0.1f)
{
print("rigid body is nearly stationary.")
}
This detects basically if the vehicle is moving ahead of backward with respect to its own axis instead of detected velociy with respect to global axis. So if vehicle has negligible movement with respect to own forward axis, then it is nearly static.
The answer is difficult to read, so I cached the variable.
float inverseZDir = rigidbody.transform.InverseTransformDirection(rigidbody.velocity).z;
if(inverseZDir < 0.1f && inverseZDir > -0.1f)
{
print("rigid body is nearly stationary.")
}
Your answer
Follow this Question
Related Questions
Distribute terrain in zones 3 Answers
C # Applying Velocity to Rigidbody 1 Answer
Prevent rigidbody from colliding 1 Answer
Transferring velocity from kinematic to a rigid body 0 Answers