• 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
4
Question by Nethara · May 21, 2014 at 02:27 AM · physicsrigidbodytimescaleslowing-down

Slow Time for a single Rigid Body

I'm working on a project where the player can slow time on certain objects (or in an area), but I can't figure out how to get this to apply to a rigid body. I need the rigidbody to fall/rotate/everything slower while affected, without messing up the rest of the game (anything not affected by the slow, for example). Other than being slower, it should act normally, and other things should interact with it correctly too (such as allowing the player to jump on it as it goes).

Is this possible, and/or how would it be done?

[Edit]:

My first attempt was to try to personally handle the physics update with MovePosition and MoveRotation, manually applying the rigidbody's velocity and angular velocity, like so:

 float dt = Time.fixedDeltaTime * timeScale;
 rigidbody.MovePosition( transform.position + rigidbody.velocity * dt );
 rigidbody.MoveRotation( transform.rotation * Quaternion.Euler( rigidbody.angularVelocity * dt ) );

I'm not 100% sure that this would be the way to do these calculations, but either way it doesn't work, because I can't get the rigidbody to stop updating itself without setting it to kinematic, but then it won't update things like gravity...any thoughts?

[Edit2]:

Is there any way to make a rigidbody stop moving itself, but still respond to all other collisions (so that I could potentially use MovePosition and MoveRotation, with my own timescale, while still maintaining normal behavior when hitting things)? I can make it kinematic, but then I can't get it to collide.

Comment
Add comment · Show 4
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 Maerig · May 21, 2014 at 02:29 AM 0
Share

Something like this, maybe ?

 rigidbody.velocity /= slowFactor;
avatar image Nethara · May 21, 2014 at 02:32 AM 0
Share

No, that wouldn't work...it would either continuously lower the velocity, or only occur once at the start of the effect, and wouldn't change rotation or gravity or anything like that...I want the rigidbody to act slower while affected.

avatar image doggan · May 21, 2014 at 02:39 AM 0
Share

What about adjusting the drag and angularDrag of the affected objects?

avatar image Nethara · May 21, 2014 at 02:42 AM 0
Share

Unfortunately, drag would cause it to slow down over time, which wasn't the intention. The ideal situation would have the rigidbody slow down immediately, then speed back up again after the effect ends.

5 Replies

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

Answer by Nethara · May 21, 2014 at 10:07 PM

Here's the solution that I'm going with (for now, at least). It'll probably need to get tweaked as I move along, and/or optimized (I don't like all the division I have to do), but it seems to work for now. Thanks to HarshadK for links that helped me get this working. The code in Update() is just for testing.

 bool first = true;
     
     [SerializeField]
     private float _timeScale = 1;
     public float timeScale {
         get { return _timeScale; }
         set {
             if( !first )
             {
                 rigidbody.mass *= timeScale;
                 rigidbody.velocity /= timeScale;
                 rigidbody.angularVelocity /= timeScale;
             }
             first = false;
     
             _timeScale = Mathf.Abs(value);
     
             rigidbody.mass /= timeScale;
             rigidbody.velocity *= timeScale;
             rigidbody.angularVelocity *= timeScale;
         }
     }
     
     void Awake()
     {
         timeScale = _timeScale;
     }
     
     void Update() {
         timeScale = ( Input.GetButton("Fire2") ? 0.25f : 1 );
     }
     
     void FixedUpdate () {
         float dt = Time.fixedDeltaTime * timeScale;
         rigidbody.velocity += Physics.gravity * dt;
     }
Comment
Add comment · Show 2 · 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 Brian-Crandell · Feb 27, 2015 at 05:09 PM 0
Share

I took basically the same approach, except your version is more complete, accounting for mass and such. However, I encountered the same problem: Gravity was slower, but still not slow enough to be proportional, causing objects to fall faster (relatively speaking). I honestly don't understand why, but simply dividing by mass seems to give perfect results.

 private void FixedUpdate()
 {
    float delta = Time.fixedDeltaTime * timeScale;
    rigidbody.velocity += Physics.gravity / rigidbody.mass * delta;
 }
avatar image Eluem · Jan 23, 2016 at 05:54 PM 1
Share

Nice work around! I like it. You don't really need to worry too much about the efficiency either, as long as you're not changing the timescale constantly.

However, what do you think of this version to improve efficiency slightly?

 public float timeScale {
          get { return _timeScale; }
          set {
              value = $$anonymous$$athf.Abs(value);
             float tempTimeScaleApplied = value/timeScale;
              _timeScale = value;
      
              rigidbody.mass /= tempTimeScaleApplied;
              rigidbody.velocity *= tempTimeScaleApplied;
              rigidbody.angularVelocity *= tempTimeScaleApplied;
          }
      }


As long as _timeScale always initializes to 1, it should be fine, no? Otherwise you do need a first still.. but it can still reduce the number of maths overall, right? :D

Edit: Just realized that I don't think either of these handle 0 timeScale too well, heh... might want to put some code in to prevent that too... or to handle it as a special case.

avatar image
0

Answer by screenname_taken · May 21, 2014 at 07:24 AM

Try putting the code that worked in decelerating the rigid body into a trigger with OnTriggerStay(). So it will affect it while in there.

OnTriggerEnter() save the acceleration and then restore it with OnTriggerExit().

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 Nethara · May 21, 2014 at 09:20 PM 0
Share

The issue isn't applying/removing the effect, I can't get Unity's rigidbody physics to slow down for that one item.

avatar image screenname_taken · May 22, 2014 at 08:47 AM 0
Share

Ah. don't think you can mess with just one object's gravity but i'm not sure. Have you tried messing around with its mass?

avatar image Nethara · May 23, 2014 at 07:08 PM 0
Share

The solution I ended up going with (marked as answer above) was to turn off Use Gravity on the rigidbody, apply gravity myself (altered by the timescale), increase mass based on the timescale, and reduce velocity and angular velocity ONLY when the timescale is changed. Seems to work pretty well.

Changing the mass alone wouldn't affect gravity (it's just handled as acceleration, not force).

avatar image
1

Answer by HarshadK · May 21, 2014 at 08:51 AM

Based on your [Edit2], you might want to take a look at Rigidbody.Sleep and Rigidbody Sleeping

Also for overall question, check answers to this question: Decreasing timescale for a single object and this one: How do I speed up the simulation of a rigidbody?

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 Nethara · May 21, 2014 at 09:18 PM 0
Share

I tried using sleep but it doesn't really work, because sleep arrests any movement and zeroes out velocities, plus it wakes up automatically if anything hits it. I tried it, but it didn't work.

The first link isn't what I need...I know how to change the timestep for things that I control myself...the issue is the rigidbody physics built into Unity.

The second link might be a little more useful...I'll play with it and see if I can make it work how I want.

avatar image
2

Answer by ludiq · Apr 11, 2015 at 03:35 PM

I know this is an old-ish question, but I managed to solve the problem consistently, if you're interested. I published a plugin in the asset store for time control that handles this case and a lot more: [removed, sorry!]

The whole set of calculations is actually quite complicated to make it work in every case, but I'll try to explain it roughly.

Your first hunch was good. You have to modify the velocity by a certain factor. However, since we're touching velocity and not acceleration, we should divide it by the derivative of the time scale, not the time scale itself. In other words:

velocity *= newTimeScale / lastTimeScale

For example, if the object becomes slowed at half speed (0.5) in a frame, we multiply its velocity by 0.5 / 1 = 0.5. On the next frame, since it stays at 0.5, we multiply by 0.5 / 0.5 = 1, that is, we don't actually change it.

You should also apply similar calculations to angular velocity and drag.

Finally, there are some other considerations to factor in for adding forces and handling collisions, but that's too complicated for a single answer. This should get you started, though :)

Comment
Add comment · Show 5 · 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 meat5000 ♦ · Apr 11, 2015 at 03:35 PM 0
Share

O$$anonymous$$ stop it.

avatar image ludiq · Apr 11, 2015 at 03:43 PM 0
Share

Sorry, didn't know there was a rule against advertising assets (perhaps the FAQ should be updated?). I removed the link, but I left the rest of the answer, because that's really the way to do it. :)

avatar image meat5000 ♦ · Apr 11, 2015 at 03:47 PM 1
Share

As it's a paid asset I have allowed one to be published on another thread as it is relevant. It would be inappropriate to duplicate the link on many threads.

There is a section on the forums where you can post a link to your finished product.

avatar image ludiq · Apr 11, 2015 at 03:49 PM 0
Share

I totally understand, I posted it on the forum already, but seeing as it could solve a lot of these questions, I figured I would post it here. I tried removing all the links in my other answers, but feel free to delete them (apparently I can't?). I still believe the FAQ should be updated, because it isn't clear on this topic.

avatar image GR1MFR0ST · Jun 27, 2019 at 08:14 PM 0
Share

Hey i know this is an old post, but ive trying to build something similar to what it seems you have built already(not the same) but im trying to have a separate section in my code that changes the physics properties when the object is "slowed" would you be able to give me a lead or point me in the direction of what i would need to slow something down if it gets hit with an impulse? is it just different math with the velocity, mass, gravity, etc? or is there more to it? would you be able to point me in the right direction for this?

avatar image
0

Answer by tzadik10 · Jun 27, 2017 at 05:29 PM

Yo need multiply the TIme.fixedDeltaTIme by Time.timeScale

Example runnig physics on 50 frames

 Time.fixedDeltaTime = 0.02F * Time.timeScale;
 or 
 Time.fixedDeltaTime = (1/50) * Time.timeScale;

https://docs.unity3d.com/ScriptReference/Time-timeScale.html

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

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.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

26 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

Related Questions

Physics behave weirdly after timeScale change 1 Answer

TimeScaling & Rigidbody problem 0 Answers

Slow motion for Physics game 2 Answers

rigidbody2d.AddForceAtPosition Doesn't Add Horizontal Movement? 1 Answer

Fireing a tank projectile. 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