Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by aman_jha · Jul 02, 2014 at 03:27 PM · c#rigidbodyvelocitystop

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?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

5 Replies

· Add your reply
  • Sort: 
avatar image
8
Best Answer

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;
         }
     }
 }




Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image fafase · Jul 03, 2014 at 12:42 AM 0
Share

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.

avatar image aman_jha · Jul 03, 2014 at 05:52 PM 1
Share

Thanks for this awesome script! This is really accurate, and even though it's complex it works with all the bells and whistles. :)

avatar image AndyMartin458 · Jul 05, 2014 at 11:28 PM 0
Share

@Yoman No prob!

avatar image hangemhigh · May 03, 2015 at 04:08 AM 0
Share

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.

avatar image minhbo · Oct 16, 2016 at 09:00 AM 0
Share

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.

Show more comments
avatar image
20

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;
     }
 }
Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image aman_jha · Jul 03, 2014 at 05:53 PM 0
Share

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 :)

avatar image boinst2 · Jul 06, 2014 at 12:24 AM 0
Share

@Yoman that's exactly what you asked for :)

avatar image Kiwasi · Jul 06, 2014 at 04:49 AM 0
Share

This is the better method. You could improve it slightly by checking against velocity.sqr$$anonymous$$agnitude ins$$anonymous$$d.

avatar image liowweiting · Apr 13, 2016 at 11:34 AM 0
Share

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);
     
 }
 

}

avatar image b1gry4n liowweiting · Apr 13, 2016 at 12:27 PM 0
Share

@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.

avatar image Ryanless · May 05, 2016 at 10:51 PM 0
Share

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.

Show more comments
avatar image
5

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

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jjxtra · May 05, 2016 at 10:38 PM 0
Share

Best answer and only real reliable way

avatar image Codorr · Apr 15, 2018 at 03:00 PM 0
Share

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

avatar image PRINTALOT · Feb 21, 2019 at 03:29 PM 0
Share

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

avatar image
2

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;
     }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

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.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image AndyMartin458 · Aug 31, 2020 at 06:33 PM 0
Share

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

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

34 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

C# Bullets do not fly, just fall... 3 Answers

Unity relative velocity limiting 0 Answers

RigidBody clips into corners 3 Answers

GameObject disappears when velocity is set to (near) zero. 1 Answer

Predict Spherical Ball Collision Direction 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges