Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Calling the physics simulation from C#

Discussion in 'Physics Previews' started by yant, Dec 6, 2016.

  1. Fergicide

    Fergicide

    Joined:
    Mar 19, 2016
    Posts:
    21
    No prob. Understandable response and one I've felt many times myself. Was uncertain if topic was still alive. Will strip down my mess of old code into something instructive and post it. Shake my tree if I haven't responded in three or four days -- will try to get something posted in 24 hours. Hopefully I'm on topic and providing the right solution to the problem. No, I've never switched off autosimulation -- until a few days ago when I learned it could be done while looking through a "Best Unity Tips" thread pointing out you can do manual physics simulation to get natural looking placement of static objects.
     
  2. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    418
    Don't feel any pressure to release something quickly. Just a little annoying not having any details. I'd post your solution in the Physics forum or one of the existing topics on time-steps and achieving smooth movement. I assume you've read most of the articles and other forum posts on the subject. I also own UFPS 1.x and that seems to have solved the problem as well, but I haven't figured out how they did it yet.
     
  3. Fergicide

    Fergicide

    Joined:
    Mar 19, 2016
    Posts:
    21
    Home from work, so looking at this now. Good news is, I documented what I did back in Aug 2018. Probably it won't make a lot of sense, because the controller I wrote was a "wall walker" type with alternating gravity so the player can traverse any surface -- see here . But it does point out the important bits of how to keep your fixedupdate behaving nicely with your update. I'm throwing this up as a temporary measure while I reconstruct my old code in simpler (and repeatable) fashion. This doco might very well give you enough of the puzzle to complete your own prototype before I post my reference code. Or it might just confound. In that case, sit tight and I'll have something saner soon.
     
    SugoiDev likes this.
  4. Fergicide

    Fergicide

    Joined:
    Mar 19, 2016
    Posts:
    21
    Here you go. I found an earlier messy prototype, so I'm not going to reinvent the wheel. I loaded this into 2018.4 and everything still works fine. As I state in my brief documentation above, what goes in FixedUpdate versus Update is key to solving the stutter issue.
     

    Attached Files:

    IsaiahKelly and SugoiDev like this.
  5. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    418
    Thanks for sharing! This definitely makes up for your early post. Haven't been able to look at it much yet, but it looks like you're basically caching inputs and only applying them during fixed update using forces with rigidbody interpolation enabled. So you're simply taking advantage of Unity's built-in smoothing system. This works well but it comes at the cost of responsiveness, since input is now locked to the physics update rate. So it may not work for everyone.

    My first impression from your prototype was that movement is very slow and sluggish, but I may just need to tweak some settings to fix that. I hope to eventually write an in-depth article on the wiki about the subject, to help everyone in the community learn how to get smoother movement in Unity, since this appears to be such a common issue.
     
  6. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    418
    You're logic is kind of backwards. If you only pull for onetime input events - like jump - in fixed update, then you'll miss them entirely if someone triggers the input between a fixed update. So these kinds of inputs should always be collected in update to avoid missing them. Something like movement input can actually be collected in fixed update because it's contentious.
     
  7. Fergicide

    Fergicide

    Joined:
    Mar 19, 2016
    Posts:
    21
    >> movement is very slow and sluggish,

    Just change the various values.

    I need to check my gravity walker controller, which was a later incarnation of the CC because, for example, I don't remember interpolation being switched on in that later iteration. It's also possible I moved all input collection to Update. Going back to rewrite the thing as a proper CC, with vaulting and switchable gravity control has been on my list for over a year, and at this stage has basically slipped into oblivion. If my stuff gave you ideas on how to solve the problem on your own and better, that's great and I look forward to checking out that wiki post.
     
  8. Noogy

    Noogy

    Joined:
    May 18, 2014
    Posts:
    130
    Just wanted to chime in with appreciation for Physics.autoSimulation. I've been having timing issues for over a year on my production, and had exhausted all options until I discovered the ability to turn off autosimulate and to manually run the simulation myself. A combination of capturing the current framerate along with a manual Simulate() has solved nearly all of my problems.
     
    yant likes this.
  9. Fergicide

    Fergicide

    Joined:
    Mar 19, 2016
    Posts:
    21
    Turns out you can avoid wrestling with FixedUpdate and Update by doing one simple thing:

    Don't parent the camera to the rigidbody.

    The timing conflict stems from the camera being bolted to the slower-updating rigidbody gameobject. Once you free it, the camera can go back to updating at monitor refresh rate. The trick is to give the camera a smooth-follow script to lerp its position on the Updates between the slower FixedUpdate rigidbody movements.

    Here's a demo (crank to 720p60 for clarity). Physics timings are Unity defaults (FixedUpdate every 1/50). Vsync is on by default (60 hz). Player left/right rotation gets applied to the rigidbody to turn it; up/down rotation gets applied to the camera only (in addition to matching the rigidbody's left/right rotation, now that the camera has no parent).



    I'm glad to be no longer fighting FixedUpdate for smooth movement. Prior to this, I was using the script below (which must be set to run after the 'default' time in the script execution list, so that it is the last thing to run in Update) to run physics at the refresh rate (60 hz for my screen), and doing all rigidbody coding in Update, which guaranteed smooth motion, but I'm unsure what, if any, drawbacks there might be to bypassing FixedUpdate entirely. I know that Unity themselves will be adding an option to "run physics in Update", which I assume will feature substepping like Unreal Engine.

    Code (CSharp):
    1.     public class PhysicsManualUpdate : MonoBehaviour
    2.     {
    3.         [Tooltip("Override physics with manual stepping.")]
    4.         float delay, accumulator;
    5.         const float oneFrame = 1 / 60.0f;
    6.         static MonoBehaviour instance;
    7.  
    8.         private void Awake()
    9.         {
    10.             // Enforce singleton.
    11.             if (instance == null) instance = this;
    12.             else DestroyImmediate(this);
    13.         }
    14.  
    15.         void OnEnable()
    16.         {
    17.             Physics.autoSimulation = false;
    18.         }
    19.  
    20.         void OnDisable()
    21.         {
    22.             Physics.autoSimulation = true;
    23.         }
    24.  
    25.         void Update()
    26.         {
    27.             // do nothing if the automatic simulation is enabled
    28.             if (Physics.autoSimulation) return;
    29.  
    30.             accumulator += Time.deltaTime;
    31.  
    32.             while (accumulator >= oneFrame)
    33.             {
    34.                 Physics.Simulate(oneFrame);
    35.                 accumulator -= oneFrame;
    36.             }
    37.  
    38.             // Here you can access the transforms state right after the simulation, if needed
    39.         }
    40.     }
    And here's camera code (modified from another's script) that runs in LateUpdate to match the camera to the rigidbody position/rotation, with smoothing:

    Code (CSharp):
    1.  
    2. Vector3 wantedPos = new Vector3(target.position.x, target.position.y + height, target.position.z);
    3. Vector3 currentPos = thisTransform.position;
    4.  
    5. // Damp the height
    6. wantedPos = Vector3.Lerp(currentPos, wantedPos, heightDamping * Time.deltaTime);
    7.  
    8. // Set the height of the camera
    9. thisTransform.position = wantedPos;
    10.  
    11. // Set rotation to match.
    12. if (handleYRotation)
    13. {
    14.    thisTransform.localRotation = target.rotation * Quaternion.AngleAxis(inputBB.rotationYXfer, Vector3.left);
    15. }
    16. else
    17. {
    18.    thisTransform.rotation = target.rotation;
    19. }
    20.  
    I should also say that I'm moving the player rigidbody with force:

    rb.AddForce(applyForceXZ, ForceMode.Force);

    and using a counterforce to squelch movement when player input stops. Rigidbody has interpolation set to None, being no longer needed since the player rigidbody mesh is switched off and invisible.
     
    Last edited: Jan 8, 2020
    hippocoder likes this.
  10. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Making the camera a child of anything except a container is awful game development practise, regardless. It is typically used in starter learning materials, and should be avoided at all costs for any real game because there is absolutely no control otherwise and a given object could be destroyed or move in an undesired manner.
     
    Fergicide likes this.
  11. Fergicide

    Fergicide

    Joined:
    Mar 19, 2016
    Posts:
    21
    Another important point, thank you, hippocoder: the risk of the parent getting destroyed unexpectedly, and there goes your camera.

    I want to be sure this thread shows up in any Google search for the topic of "how to get smooth camera movement in unity with a rigidbody and fixedupdate" because I know I'm not alone in finding out way too late about this crucial bit of information. So I'm going to repeat it using -- and my apologies but it's warranted -- the largest font possible:

    Never parent your camera to anything.

    There will be reasonable exceptions, but that's the rule I now live by. Live, gamedev, and learn. Take manual control of your camera. Give it its own brain and its own independence. Live FixedUpdate free.
     
    ModLunar likes this.
  12. Fergicide

    Fergicide

    Joined:
    Mar 19, 2016
    Posts:
    21
    Further to The Adventure of Rigidbody Player Controllers...

    When the player stops giving input, I damp rigidbody movement by an adjustable amount to smoothly and quickly bring the player to a halt. This is done by applying a proportional counter force to the rb until its velocity is zero (sqrmagnitude comparisons!).

    At first I couldn't figure out why there was always a residual bit of damping even when the damping value was set insanely high and, in theory, should've been applying so much counter force as to halt the rb immediately.

    Code (CSharp):
    1. mouseXInput = Input.GetAxis("Mouse X");
    2. mouseYInput = Input.GetAxis("Mouse Y");
    3. moveXRawInput = Input.GetAxisRaw("Horizontal");
    4. moveYRawInput = Input.GetAxisRaw("Vertical");
    Yep, I was using GetAxis for mouse input, which automatically adds smoothing, thus my inescapable residual damping. Switching to the unmodified GetAxisRaw was what I should've been doing.
     
  13. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    418
    @Fergicide This is really going off-topic and should really be continued in a new or more appropriate thread, but here's my input anyway.

    Yes, this is a pretty effective technique and it works great for smoothing out staircase stepping but there are a few drawbacks I've found with it, at least in my tests. I'm sure there are ways to negate most of these but I'm not sure how much work is involved.

    1. Lerping the camera means it will lag behind actual player movement and may also not sync with actual fast or erratic movement correctly at times, e.g. falling down, going up an elevator, etc.
    2. Interactions with other physics bodies (e.g. pushing a box) will look very jerky since only camera motion is smoothed.
     
  14. Fergicide

    Fergicide

    Joined:
    Mar 19, 2016
    Posts:
    21
  15. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,512
    I'm not countering anything that's been said here but I wanted to point out that if you absolutely must have your Camera parented to a GO with a Rigidbody, it's updated to the position of the Transform component on that GO, not to the position of the Rigidbody component. The subtle difference here being that if you were to use Rigidbody Interpolation, the Transform is updated per-frame moving from the previously Rigidbody position to the current Rigidbody position (also rotation). Just highlighting what interpolation does.

    I'm not saying this is what you want, just that updating your camera at the frequency of the physics update isn't a fixed thing if you use Rigidbody Interpolation. I agree though that your camera movement shouldn't be hardwired to the GO the Rigidbody is on allowing you to perform whatever camera movement/smoothing/limits you want.
     
    Fergicide likes this.
  16. DerDicke

    DerDicke

    Joined:
    Jun 30, 2015
    Posts:
    291
    You should really update your learning resources. Anyone learning Unity is considering parenting the cam to the player is the preferred way to go, just because *every* Unity learning resource does it. Going away from this pattern is not easy... we all learned it the wrong way.
     
  17. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,512
    Well unfortunately that's not something I can do unless I change jobs. ;)

    It certainly might be used but it's a stretch to say every learning resource does it. Also, it's not like you should never do this. It's a nice quick way to get started with camera tracking.

    If every single tutorial showed you how you should do everything perfectly then they'd be much longer, more verbose and much more confusing. There are stages of learning.

    I remember progressing through school and each year they said, "I know we showed you this last year but that was kind of a simplification to get you started, here's how it should really be done". ;)
     
  18. DerDicke

    DerDicke

    Joined:
    Jun 30, 2015
    Posts:
    291
    Shows why US is somewhere in the thirties in Pisa studies ;-)
     
  19. AlkisFortuneFish

    AlkisFortuneFish

    Joined:
    Apr 26, 2013
    Posts:
    959
    Melv is not in the US or from the US. ;-)
     
  20. DerDicke

    DerDicke

    Joined:
    Jun 30, 2015
    Posts:
    291
    Too bad, so my sarcasm was wasted ;-). No, didn't want to complain, just would appreciate better samples. My dumb brain is easily misled.