Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 SVC Games · Oct 15, 2015 at 11:01 AM · rigidbodylagtranslatemovepositionunitypackage

MovePosition not as precise as Translate with Kinematic rigidbodies (example unitypackage included)

So I've been doing some testing and I've come to the conclusion that MovePosition have a lag when moving a rigidbody. The included unitypackage comes with a simple scene with 2 instances of a prefab.

(Download UnityPackage (10kb))

That prefab is a rigidbody with:

  • Interpolate: Set to "Interpolate"

  • Use gravity: Unchecked

  • Is Kinematic: Checked

In Update, the arrow keys are scanned to check if the game objects must be moved around.

One of the instances (Player 1) moves it's position using transform.Translate in Update. The other (Player 2) uses rigidbody.MovePosition in FixedUpdate, where all physics interactions should be.

The code (very simple) is as follows:

 [Range(1, 2)]
 public int PlayerId = 1;
 public float speed = 5;

 private Rigidbody rigidBody;
 private Vector2 input;
 
 void Awake()
 {
     rigidBody = GetComponent<Rigidbody>();
 }

 
 void Update () {
     input = new Vector2();
     if (Input.GetKey(KeyCode.LeftArrow)) { input.x = -1; }
     if (Input.GetKey(KeyCode.RightArrow)) { input.x = 1; }
     if (Input.GetKey(KeyCode.UpArrow)) { input.y = 1; }
     if (Input.GetKey(KeyCode.DownArrow)) { input.y = -1; }

     if (PlayerId == 1)
     {
         Vector3 movement = Vector3.right * input.x * speed * Time.deltaTime;
         movement += Vector3.forward * input.y * speed * Time.deltaTime;                  
         transform.Translate(movement);
     }
 }


 void FixedUpdate()
 {     
     if (PlayerId == 2) {
         Vector3 movement = Vector3.right * input.x * speed * Time.deltaTime;
         movement += Vector3.forward * input.y * speed * Time.deltaTime;
         rigidBody.MovePosition(rigidBody.position + movement);         
     }
 }

In theory both game objects should move at the same time, maintaining their relative position between each other. But if you run this sample, you will notice that Player 2 have a noticeable lag between the moment the arrow is pressed and its actual movement on the screen.

While Player 1 (using translate) moves instantly as it should, Player 2 seems to do it at a different time. If you follow Player 2 in the Scene View (using Shift + F) and keep going in one direction, you will notice that eventually it will surpass Player 1.

Is there a solution to this problem? Is there something I'm missing or not understanding? This lag completely ruins precision gameplay, but I want to use the physics system.

Thanks in advance.

rigidbodytrouble.zip (9.6 kB)
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

1 Reply

· Add your reply
  • Sort: 
avatar image
3

Answer by Bunny83 · Oct 15, 2015 at 11:44 AM

I'm not sure if you are familiar with how FixedUpdate works. FixedUpdate is always executed before Update. However it's "fixed" (not at a fix rate but with a "fixed" time / deltaTime).

Time.deltaTime usually returns the time the last frame took overall. However inside FixedUpdate Time.deltaTime returns "fixedDeltaTime" instead. That's because FixedUpdate doesn't run necessarily when Update runs or it might even run multiple times within one frame to keep it's execution rate "pseudo constant".

In pseudo code Unity's main loop looks something like this:

 while(true)
 {
     ReadInput();
     while(Time.fixedTime < Time.time)
     {
         RunFixedUpdate();
         UpdateInternalPhysics();
         Time.fixedTime += Time.fixedDeltaTime;
     }
     RunUpdate();
     Render();
     Time.time += Time.deltaTime;
 }

"Time.fixedDeltaTime" is a constant value it's what you have set as your fixed timestep. (Usually 0.02 == 50fps)

As you can see if fixedDeltaTime is larger than the actual deltaTime FixedUpdate might skip an execution since the amount Time.time advanced the last frame doesn't exceed the current "fixedTime". Both Time.time and Time.fixedTime will advance at the same speed. They never drift apart. However they will almost never be equal since they are advanced at different intervals. FixedUpdate (with a timestep of 0.02) will always be called 50 times in a sec while the Update rate depends on the performance and maybe vsync limitations.

If your framerate drops to 5 fps, FixedUpdate will be called roughly 10 times per frame. If you have a framerate of about 100fps FixedUpdate will be called about every second frame. So every other frame no FixedUpdate call is made.

You get the smoothest movement if you sync the movement with the visual update. FixedUpdate just ensures a constant rate which is important if your movement should be the same at all framerates.

As we all know using Time.deltaTime ensures that a linear change which we apply each frame is time based and frame independent. However that only works for linear changes. Since acceleration (linear change of velocity) results in a quadratic change in position there's an error which is different depending on the framerate. Using a constant rate for physics calculations ensures that you always get the same result after a certain amount of time.

Using FixedUpdate for movement will always introduce a bit of stutter since sometimes you might get two visual updates but only one actual movement so it looks like it's stuck for a frame.

As far as i know it should be no problem to use MovePosition inside Update especially since you have just a linear motion (no acceleration). The advice to use FixedUpdate applies to when using forces. Since forces are applied inside the Internal physics step you should apply the force right before Unity's physics system internally updates the velocity / position.

edit
I once made a Webplayer build to visualize how FixedUpdate works. Of course you need a browser that still supports the Unity webplayer plugin ^^. You can adjust the virtual "FPS rate" and the "FixedRate" at the bottom. The simulaition speed is 100 times slower than realtime(can also be adjusted). Each red section represents "one frame" where each blue rect represents an Update call(once per frame) while the magenta rects represents an FixedUpdate call. You can also see how Time.time and Time.fixedTime will change over time.

Comment
Add comment · Show 9 · 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 SVC Games · Oct 15, 2015 at 12:07 PM 0
Share

Following your answer I've modified the code, putting $$anonymous$$ovePosition into Update (because as you said it is a linear motion) but still I'm having lag when moving the GO with $$anonymous$$ovePosition that doesn't happen with Translate:

 [Range(1, 2)] 
 public int PlayerId = 1;
 public float speed = 5;

 private Rigidbody rigidBody;
 private Vector2 input;
 private Vector3 movement;
    
 void Awake()
 {        
     rigidBody = GetComponent<Rigidbody>();
 }


 void Update()
 {
     input = new Vector2();
     if (Input.Get$$anonymous$$ey($$anonymous$$eyCode.LeftArrow)) { input.x = -1; }
     if (Input.Get$$anonymous$$ey($$anonymous$$eyCode.RightArrow)) { input.x = 1; }
     if (Input.Get$$anonymous$$ey($$anonymous$$eyCode.UpArrow)) { input.y = 1; }
     if (Input.Get$$anonymous$$ey($$anonymous$$eyCode.DownArrow)) { input.y = -1; }

     movement = Vector3.right * input.x * speed * Time.deltaTime;
     movement += Vector3.forward * input.y * speed * Time.deltaTime;

     if (PlayerId == 1)            
         transform.Translate(movement);
     
     if (PlayerId == 2)
         rigidBody.$$anonymous$$ovePosition(rigidBody.position + movement);        
 }
 

Is it as if $$anonymous$$ovePosition lags somehow, even reducing the fixed timeStep to 0.166667

avatar image meat5000 ♦ SVC Games · Oct 15, 2015 at 12:39 PM 0
Share

The nature of Interpolation is guaranteed to add error. This is because it is working things out based on information it has got. A translate is a one time operation but a $$anonymous$$oveposition is actually rendered over multiple frames if the interpolation is set in the rigidbody. It states this in the docs :

If Rigidbody interpolation is enabled on the Rigidbody, calling Rigidbody.$$anonymous$$ovePosition results in a smooth transition between the two positions in any intermediate frames rendered. This should be used if you want to continuously move a rigidbody in each FixedUpdate. Set Rigidbody.position ins$$anonymous$$d, if you want to teleport a rigidbody from one position to another, with no intermediate positions being rendered.

"Use .position if you want no intermediate frames rendered" (To paraphrase)

A Translate has no such intermediacy.

Its not really an issue but a $$anonymous$$ovePosition is more intensive than a Translate as it performs a sweeptest between the two points to deter$$anonymous$$e is any collisions could have occured, I do believe.

avatar image meat5000 ♦ meat5000 ♦ · Oct 15, 2015 at 12:55 PM 0
Share

This case re$$anonymous$$ds me of the common problem of 'Camera Jitter' where either the camera or object appear to jitter/shake when moving. The fix that worked for me was to calculate the acculative fixedDeltaTime that occured between Updates and plug that figure in the the calculations. (Where I had success with this, the other guy didnt).

http://answers.unity3d.com/questions/1012337/player-or-background-stutter.html

The reason I add this in here, if you freeze your "Update" object and just observe the "FixedUpdate" object it appears to stutter periodically, moving in bursts.

Show more comments
avatar image SVC Games · Oct 16, 2015 at 06:44 AM 0
Share

Sorry @meat5000, I meant, Position. Even though I still notice a small amount of lag compared to just doing transform is closer to what I want. I'll have to learn to live with that rounding problem :P

avatar image meat5000 ♦ SVC Games · Oct 16, 2015 at 08:46 AM 0
Share

Same thing dude. $$anonymous$$oving by position is teleporting and wont properly register collisions. Dont get me wrong, they can still occur but objects are very likely to pass through colliders.

avatar image SVC Games meat5000 ♦ · Oct 16, 2015 at 09:35 AM 0
Share

After testing it works acceptably with my scenario. But you are right, I see how it won't work in other situations. I'm a little perplexed that this see$$anonymous$$gly common situation is so complicated and Unity kind of force you to apply forces on the rigidbody...

Show more comments

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

6 People are following this question.

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

Related Questions

Rigidbody.MovePosition relativeTo parent 0 Answers

MovePosition in Rigidbody Ignoring Y axis? 0 Answers

Rigidbody.AddForce equivalent of transform.Translate? 3 Answers

Character - Collider With Scene 0 Answers

How to make an NPC ball to chase player by rolling, not moving 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