Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Time.timeScale is Having a Strange Effect on Physics

Discussion in 'Scripting' started by PirateMonkey, Sep 15, 2014.

  1. PirateMonkey

    PirateMonkey

    Joined:
    Jun 24, 2014
    Posts:
    28
    Hey all,

    I am currently building a 2d physics-based game. I've built a moving character who can shoot bullets (which naturally travel much faster than the character).

    Recently I've tried implementing slow-mo into the game by pressing space. The issue I'm having is that it seems to affect the physics-based objects in different and unexpected ways. The main issue is that the bullets become slower relative to the character - the lower the slow-mo timescale, the slower the bullet relative to the character. With a Time.timeScale as low as 0.1, the character can actually travel faster than the bullet and I have no idea why.

    Any ideas? I would really appreciate the help! :)
     
    user2678 likes this.
  2. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    597
    Time.timeScale affects everything except physics. I'm pretty sure Time.fixedDeltaTime is used for how quickly Physics are updated. If you lerp something, Time.timeScale will slow that down. If you drop a ball with a rigidbody, Time.fixedDeltaTime will slow down that. If you want everything to slow down you have to change both. Fixed Time (as it is called in the Inpector) is at 0.02 by default. To get smooth physics in slo-mo I typically lower it down to about 0.005. Be sure not to make it too low otherwise Unity will crash because its checking physics too quickly.
     
    tannerschwab2000 likes this.
  3. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    nope. timeScale affects everything.

    How are you controlling your projectiles
     
  4. PirateMonkey

    PirateMonkey

    Joined:
    Jun 24, 2014
    Posts:
    28
    Hey, here is some of the relevant code from my 'shooting' script:

    Code (JavaScript):
    1. //missile variables
    2. var missileFireRate : float = 0.5;
    3. private var missileNextShot : float = 0.0;
    4. var missilePrefab : Transform;
    5. var missileForce = Vector2(200,200);
    6.  
    7. ...
    8.  
    9. function FixedUpdate ()
    10. {
    11.  
    12. ...
    13.  
    14. if(Input.GetKey(fireWeapon) && SubControl.isShotEnabled == true)
    15.     {
    16.         if(primaryActive == true && missileActive == true)
    17.             {
    18.                 if(Time.time >= missileNextShot)    //Time.time is the time since frame has started
    19.                     {
    20.                         //Code generates Missile, and instantiates in the location of the Turret
    21.                         var missileInstance = Instantiate(missilePrefab, Vector3(transform.position.x, GameObject.Find("Suber").transform.position.y, transform.position.z - 0.03), transform.rotation);
    22.                         missileInstance.rigidbody2D.AddForce(Vector2.Scale(TurretRotation.difference, missileForce));
    23.                         missileNextShot = Time.time + missileFireRate;
    24.                     }
    25.             }
    26. }

    So I'm basically instantiating the missile and adding force in the direction of the turret (controlled by the mouse)
     
  5. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Likely, the player isn't using deltaTime and is actually broken. So he thinks physics are broken, when physics are actually behaving correctly.
     
    user2678 likes this.
  6. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    597
    It slows it down, but the physics object still don't update as fast. A rigidbody will move the correct distance if time is slowed down, but it doesn't update as fast. If Time.timeScale is set to 0.5, the rigidbody will get from point A to point B in half the time, but it won't do it smoothly. The physics update time (0.02) is now "increased" because time is slowed down to half speed. That means you will more easily be able to see the updates because in the time between updates it has had more time to move, which results in jumping. At normal speed the jumping is way to small to see, but when time is slowed down it becomes visible.
     
  7. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    projectile code looks fine (despite the nasty find you've lumped in there). show us your player movement code.

    Changing time scale doesnt affect the efficiency of the physics engine.

    Ive just spent a few months working on a physics based endless runner style game. I can play it at 0.1x speed or 10x speed and it comes out with the same end result.
     
  8. keenanwoodall

    keenanwoodall

    Joined:
    May 30, 2014
    Posts:
    597
    That's strange (sorry if it seems like I'm being a dick). I've been working on a space shooter and when I was making the movement script I added a slow-motion feature to mess around. When ever I pressed the space bar to trigger slow-motion, my spaceship would jump in small movements, when I lowered the fixed update time it smoothed out. I don't know why. I kinda want to download Fraps to record it and show you because I really want to figure out why I am the only one who has to change the fixed update time :)
     
  9. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    Depends how your moving your ship... I cant think of any reason for it to be jumpy at a slower speed.
     
  10. BmxGrilled

    BmxGrilled

    Joined:
    Jan 27, 2014
    Posts:
    238
    you should always make sure any time based movement is scaled using the appropriate values
    Time.deltaTime for Update() and LateUpdate()
    Time.fixedDeltaTime for FixedUpdate()
    That ensures that the right time scales are being used at least. Hope this helps! :)
     
    angrypenguin and user2678 like this.
  11. PirateMonkey

    PirateMonkey

    Joined:
    Jun 24, 2014
    Posts:
    28
    Here is the player movement code, though I believe it is functioning fine:

    Code (JavaScript):
    1. //Define move keys
    2. var moveRight : KeyCode;
    3. var moveLeft : KeyCode;
    4. var moveUp : KeyCode;
    5. var moveDown : KeyCode;
    6.  
    7. //Define forces for sub movement
    8. var cruisingForceX = Vector2(10,0);
    9. var cruisingForceY = Vector2(0,10);
    10. private var ForceX = cruisingForceX;
    11. private var ForceY = cruisingForceY;
    12.  
    13. ...
    14.  
    15. function FixedUpdate ()
    16. {
    17. //Move code
    18. if (Input.GetKey(moveRight) && !Input.GetKey(moveLeft))
    19.     {
    20.     //rigidbody2D.AddForce.x
    21.     rigidbody2D.AddForce (ForceX);
    22.     transform.localScale.x = 1;
    23.     isTurnedRight = true;
    24.     }
    25. if (Input.GetKey(moveLeft) && !Input.GetKey(moveRight))
    26.     {
    27.     rigidbody2D.AddForce (-1*ForceX);
    28.     transform.localScale.x = -1;
    29.     isTurnedRight = false;
    30.     }
    31. if (Input.GetKey(moveUp) && transform.position.y < yVelCutoff)
    32.     {
    33.     rigidbody2D.AddForce (ForceY);
    34.     }
    35.     else
    36.         {
    37.         rigidbody2D.AddForce (Vector2(0,0));
    38.         }
    39. if (Input.GetKey(moveDown))
    40.     {
    41.     rigidbody2D.AddForce (-1*ForceY);
    42.     }
    43. ...
    44. }
     
  12. PirateMonkey

    PirateMonkey

    Joined:
    Jun 24, 2014
    Posts:
    28
    I achieve movement using AddForce, so is there a way I could apply this to that code? Sorry if this is a stupid question, I am somewhat new to Unity. Thanks! :)
     
  13. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    1. You should move your Input.GetKey functions to Update

    2. Messing with the scale can mess with physics... although yours are 1/-1 respectively, so its probably not having an effect there. Is there a reason you cant use LocalRotation instead?

    3. You could multiply your forces by DeltaTime to apply some frame smoothing

    4. While we're here. you should cache this transform as well GameObject.Find("Suber"). Using Find is bad. Using it in any of the Updates is worse.
     
  14. PirateMonkey

    PirateMonkey

    Joined:
    Jun 24, 2014
    Posts:
    28
    Awesome, I appreciate the feedback! Maybe they'll fix my timescale problem as well.

    EDIT:

    For 2. Since my game is 2D I was just using that the flip the characters. But if it messes with physics I'll look into changing it to localrotation.

    3. How exactly do you do this in code?
     
    Last edited: Sep 16, 2014
    ThermalFusion likes this.
  15. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    3 is probably the source of the speed issue, at half timeScale forces would be applied at twice the rate it used to, causing an increase in speed. You'd have to implement some sort of scaling by deltaTime. Multiplying forces with it might just be close enough.
     
  16. BmxGrilled

    BmxGrilled

    Joined:
    Jan 27, 2014
    Posts:
    238
    Timescale should affect that function automatically, from what I am aware, the function uses fixedTimeDelta internally?!
     
  17. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    Should be as simple as.

    rigidbody2D.AddForce(ForceX * Time.fixedDeltaTime);

    Im not sure which is the best delta to use.. there are a few available, so try them out and see which gives you the best result.

    Possibly... not sure myself, but I would be surprised.
     
  18. BmxGrilled

    BmxGrilled

    Joined:
    Jan 27, 2014
    Posts:
    238
    It's best to use the correct delta values, deltaTime for Update/LateUpdate and fixedDeltaTime for FixedUpdate. That's what they're designed for.
     
  19. Fraconte

    Fraconte

    Joined:
    Dec 6, 2013
    Posts:
    327
    From the docs:
    "If you lower timeScale it is recommended to also lower Time.fixedDeltaTime by the same amount."
    Code (CSharp):
    1.  Time.fixedDeltaTime = 0.02F * Time.timeScale;
    And:
    "For reading the delta time it is recommended to use Time.deltaTime instead because it automatically returns the right delta time if you are inside a FixedUpdate function or Update function."

    This still confuse me:
    "Note that the fixedDeltaTime interval is with respect to the in-game time affected by timeScale."

    http://docs.unity3d.com/ScriptReference/Time-fixedDeltaTime.html
    http://docs.unity3d.com/ScriptReference/Time-timeScale.html
     
    BmxGrilled and keenanwoodall like this.
  20. BmxGrilled

    BmxGrilled

    Joined:
    Jan 27, 2014
    Posts:
    238
    Interesting, I just assumed that both deltaTime values were scaled. Thanks for the clarification! :)
     
  21. PirateMonkey

    PirateMonkey

    Joined:
    Jun 24, 2014
    Posts:
    28
    OKAY, after playing around with my scripts for a couple I think I maybe sort of understand what's going on.

    I believe the reason the missiles slow down when time is slowed is because force is applied WITHIN the if statement. So force is only added during that frame where the if(Input.GetKey(fireWeapon)...) is true. When timescale is slowed, something wonky happens to the missiles, but not to the character since force is applied constantly every frame. THEREFORE I think that the missileInstance.rigidbody2D.AddForce... line needs to be placed outside of that if statement.

    I'm going to try to get this to work, and will report back if it does.
     
  22. PirateMonkey

    PirateMonkey

    Joined:
    Jun 24, 2014
    Posts:
    28
    Okay! In my missile shooting script, I found that this did the trick:

    Code (JavaScript):
    1. missileInstance.rigidbody2D.velocity = Vector2.Scale(TurretRotation.difference, missileVelocity);
     
    Last edited: Sep 17, 2014
  23. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    This is why I suggested moving your Input checks to Update... there was a thread about it a while back about FixedUpdate missing/losing (not really the right description) Input values.
     
  24. Mohammad_021

    Mohammad_021

    Joined:
    Jan 22, 2019
    Posts:
    3
    I Have this problem too. My enemies has ragdall with configuration joint and after slow motion they rotate with no reason.
     
  25. Bananzabro

    Bananzabro

    Joined:
    Oct 19, 2020
    Posts:
    21
    Dude, have you find the answer? I have the same problem and i could not find the answer ANYWHERE