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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Is there some kind of... Late Fixed Update?

Discussion in 'Scripting' started by Marscaleb, Feb 29, 2016.

  1. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    992
    I have a number of objects in my game that use some custom collision code I built in my script. For reasons.
    I have them successfully using proper collision with the world, but I am running into a logical problem with them colliding with each other.
    Quite simply, I should have all of these objects move first, collide with the world, and THEN check to see if they collide with each other. (Because if they collide with each other, it doesn't change their position, it changes other properties.)

    But for that to work right, ALL these objects need to move first before ANY OF THEM check if they are touching each other. Otherwise one object will move, and then if it detects a collision, it could actually be detecting where that object was in the last frame, not where it should be now.

    Ideally, this is resolved with using LateUpdate. Everything moves on Update, then they check to see if they are touching on LateUpdate. But the problem is that I am using FixedUpdate. For reasons.

    So... Is there some sort of "LateFixedUpdate?" I don't see one in the documentation. If not, how can I mimic this effect?
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,745
  3. bdev

    bdev

    Joined:
    Jan 4, 2011
    Posts:
    656
    I've struggled with this one before. I haven't dealt with FixedUpdate for a year or so, so i'm not sure what unity has added since then. But yes as StarManta suggested, script execution order is probably what you want. if you maintain a list of objects (Every one that uses Fixed Update right now) you can make a script that has a higher or lower execution order and run each item in that list to make a early or late fixed update effectively.
     
  4. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    992
    I thought of that, but it doesn't really resolve this issue.
    To work properly, I need to GO BACK and execute code in a script that has already executed.

    Like this:

    Code (CSharp):
    1. FixedUpdate 1
    2. {
    3.    Object 1
    4.    {
    5.       move
    6.    }
    7.    Object 2
    8.    {
    9.       move
    10.    }
    11. ...
    12.    Object 1
    13.    {
    14.       check if touches
    15.    }
    16.    Object 2
    17.    {
    18.       check if touches
    19.    }
    20. }
    Adjusting the execution order will only grant me

    Code (CSharp):
    1. Fixed Update 1
    2. {
    3.    Object 1
    4.    {
    5.       move
    6.       check if touches
    7.    }
    8.    Object 2
    9.    {
    10.       move
    11.       check if touches
    12.    }
    13. }
     
    Last edited: Feb 29, 2016
  5. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Suggestion: Make your own LateFixedUpdate! :)

    You can do this by writing a single script that would call your LateFixedUpdate on every objects after FixedUpdate. However this script would have to be executed after all the other object, which is easily done by setting the execution order: http://docs.unity3d.com/Manual/class-ScriptExecution.html
     
    trombonaut likes this.
  6. bdev

    bdev

    Joined:
    Jan 4, 2011
    Posts:
    656
    yea so what i'm suggesting is you do something like this...
    Code (csharp):
    1.  
    2. class Body : MonoBehaviour {
    3. static List<Body> s_AllBodies = new List<Body>();
    4. void OnEnable() { s_AllBodies.Add(this);}
    5. void OnDisable() { for(;s_AllBodies.Remove(this););}
    6. void move(){}
    7. void check(){}
    8. public static void Move() { foreach(var item in s_AllBodies) item.move(); }
    9. public static void Check() { foreach(var item in s_AllBodies) item.check(); }
    10. }
    11. class PreLateUpdateRunner : MonoBehaviour { void FixedUpdate() { Body.Move();} }
    12. class PostLateUpdateRunner : MonoBehaviour { void FixedUpdate() { Body.Check();} }
    13.  
     
  7. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    992
    Hmmm... Let me see if I can follow that...

    1) make a static list to contain all of my objects that need to be updated in this way
    2) add code to have these objects add and remove themselves from that static list
    3) have my moving code in a special function, and likewise the checking code in another
    4) make a class with an early execution order which, upon fixed update, calls the move function in every object in the static list
    5) make a class with a late execution order which, upon fixed update, calls the check function in every object in the static list.

    Wow, that's pretty intense!
    I'm a bit unsure about the details of how to handle the static functions, (I've done almost nothing with static code,) but I guess I can ask for help when I run into a problem.
    But yeah, that looks like it would handle what I need to do.

    I might as well ask a couple questions about the static bits right now.
    1)That for-loop in the "onDisable" line, why is that a for-loop and not just a command? That line looks like an explosion of syntax errors that I am not sure how to plug up.
    2)Technically, I could call Body.Move() and Body.Check() in the same class, couldn't I? Separating them allows me to add code to individual classes that gets executed between Move and Check, but I could just as well have one script call them one right after the other, if I were so inclined. Right?
    3) the "s_" before AllBodies is just a naming convention, right?
    4)So... There's no problems with the command to call move in every script being in the base class? It is still only being called once, even though that code will technically exist in every body class and class that extends from body?
     
  8. bdev

    bdev

    Joined:
    Jan 4, 2011
    Posts:
    656
    answers:
    1) it just runs remove until it returns false (meaning the item is not in the list)
    2) yes, you could. however having the two runner classes would allow you to set call orders that run prior or after other scripts that use fixedupdate which may not need this move/check approach.
    3) yes, s_ generally means static. it doesn't matter what you name it.
    4) you would only want to do these checks on things that need it. but it would not be inoperable if it was in the base class and things did not use it.

    the things you have to be most careful about is that you only add items to the list once, and always remove them from the list. if you do not remove things from the list before they destroy you will eventually run out of memory. OnEnable and OnDisable generally work well for this but if you use ExecuteInEditMode it gets weird quickly.

    you could also approach this in a less object oriented manor by using events. something like this.
    Code (csharp):
    1.  
    2. class Body : MonoBehaviour {
    3. private readonly System.Action m_MoveCallback, m_CheckCallback;
    4. public Body() { m_MoveCallback = this.PreFixedUpdate; m_CheckCallback = this.PostFixedUpdate; }
    5. void OnEnable() { PreUpdateRunner.OnFixedUpdate += this.m_MoveCallback; PostUpdateRunner.OnFixedUpdate += this.m_CheckCallback; }
    6. void OnDisable() { PreUpdateRunner.OnFixedUpdate -= this.m_MoveCallback; PostUpdateRunner.OnFixedUpdate -= this.m_CheckCallback; }
    7.  
    8. void PreFixedUpdate() {..}
    9. void PostFixedUpdate() {..}
    10. }
    11. class PreUpdateRunner : MonoBehaviour {
    12. public static event System.Action OnFixedUpdate;
    13. void FixedUpdate() { var Callback = OnFixedUpdate; if(Callback!=null)Callback();}
    14. }
    15. class PostUpdateRunner : MonoBehaviour {
    16. public static event System.Action OnFixedUpdate;
    17. void FixedUpdate() { var Callback = OnFixedUpdate; if(Callback!=null)Callback();}
    18. }
    19.  
     
  9. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Its what Unity does under the hood for you. Makes you grateful to have an engine now, doesn't it.
     
    trombonaut likes this.
  10. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    897
    I'm coming to this a bit late but you should be better off separating those two collisions into separate colliders. the first collider operates as normal, hitting objects in the world, colliding and affecting movement. the second collider only hits other objects of the same type, and since its not doing actual collision, it should be a trigger instead

    these two collider objects should be on seperate objects, with each their own collision layer, doing so would allow you to edit the setting in the Physics editor to make sure that the collider hits every object except the trigger's type, while the trigger only hits other objects on the same layer.

    Making these changes in the physics editor is a great way for isolating all these physics collisions into separate logic that's easy to handle, plus it can have a pretty effective impact on improving game performance (depending on the game).

    and now that you have your own collision layer for the same object trigger, you no longer need a static list to cross reference against. your now checking by type, not by instance which has its own benefits with performance (and when it comes to anything physics related, I'll take all the performance i can get)

    likewise since the trigger version you want to do late, you should be able to make the OnTiggerEnter a coroutine and use WaitForEndOfFrame.
     
    Kiwasi likes this.
  11. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    992
    Okay, I know it's been a couple weeks, but I found I had to tie up some other pieces of code first.

    I'm starting to implement this, and as I look at it, there are a couple changes I think I ought to make.

    As I look at the code I need in the actual classes I am building, I think I want to create a new set of functions to be called.
    I would call a list of function in all the objects on the list, in an order like this:
    void preMove()
    void Move()
    void postMove()
    void Check()
    void postCheck()

    And strictly speaking, I would never run FixedUpdate in any of the body classes. In all the child classes, I would simply override the preMove, postMove, and PostCheck functions to handle all the stuff that the individual class needs.

    Now as such, I would just need one class to call those functions from within FixedUpdate. (I would probably use my GameManager, since it is a single persistent class.) So this one class would have this:
    Code (CSharp):
    1. void FixedUpdate() {
    2. Body.PreMove();
    3. Body.Move();
    4. Body.PostMove();
    5. Body.Check();
    6. Body.PostCheck();
    7. }
    This would also bring an unintended benefit that I don't need to bother with script execution order. One single script calls the functions in order on one FixedUpdate.

    Does that look like it would work right?

    The only thing that still remains that I think I would need to handle is making sure that the player is updated first, and the camera is updated second. This is because (as far as I can forsee) all other objects will have their code dependent on the camera's position, because their behavior will change if they are visible or not. (I mean, I guess being off by one frame won't be a big issue, but still, I ought to set them up properly.) My first thought is that I could simply add a couple calls in that list that just directly call the player, and then the camera. But then the player would get called to move again when Body.Move() is called. I guess I could override the player's move() function so it does nothing and the special PlayerMove() function does all of that, but that feels a bit convoluted.

    Also, I wonder if there is a problem with calling functions like Body.Move() when there are no bodies in the scene. I'm thinking of situations like being on the main menu before the game starts, there will not be any bodies in the scene. Will that cause problems if the GameManager is trying to call static functions from the body class?
     
  12. ericbegue

    ericbegue

    Joined:
    May 31, 2013
    Posts:
    1,353
    Do you actually need all theses functions or are you designing a system with the idea that it might solve every single execution order issues you might find in the future?
     
  13. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Moving a rigidbody's position doesn't actually update the PhysX stuff until AFTER FixedUpdate() has run. If you're using raycasts, just know the raycasts will be looking at the collider as it was positioned at the beginning of FixedUpdate() and won't see the changes made during FixedUpdate().
     
  14. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    992
    I already know know that the preMove() function would be used by every class that extends from this class, and most of the more complex classes would use the PostMove() function. That leaves only PostCheck() that I'm just leaving in case I need it.
    I could merge the preMove() and Move() functions into each other, but that would just result in code being needlessly duplicated.

    I'm not using rigidbody. The physics are running on original code.
    The Move() functions are moving objects and checking collisions with static collisions in the world, and the check() function is checking collisions with each other.

    EDIT: After my first run with this system, I am finding that it is calling these functions before the Start function is called, which is producing errors.
    Now off the top of my head, I could add a bool to be set in Start (and another in awake) that will be used to exit the function if it hasn't called Start yet, but I wonder if there is a more practical method that could be used instead.
    Does the system have a method to check if a class has awoken and/or started I could use?
     
    Last edited: Mar 12, 2016
  15. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    897
    its just me, but I would make a separate class to handle those update calls, even my game manager isn't a god object (it usually just handles win/lose conditions in my games). The idea is that each class should have only one responsibility. Since both classes are monobehaviours you can simply put both components on the same game object and they'll share the same persistence.

    also with this one class controlling the timing of all slaved classes, its better you make them public static UnityEvent, like OnPremove() and OnMove(). The bodies will AddListener to these UnityEvents in OnEnable(), and then RemoveListener OnDisable(). doing it this way you don't need to worry about that start/awake error you're talking about. The manager won't need a reference the objects its controlling. it doesn't need to know who is listening, just worries about when to invoke the events.

    Then you can call something like OnPreMove.Invoke(); and the UnityEvent class will handle if there are listeners or not, and if there are it will call those handling methods for you.
     
  16. steeldynamite

    steeldynamite

    Joined:
    Jun 15, 2020
    Posts:
    3
    For anyone who comes here from a google search, there's a much easier way to do this. In your FixedUpdate(), set a boolean like `_wasPhysicsUpdatedThisFrame` to `true`... then in your Update() check against that boolean and set it back to false.
     
  17. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Doesn’t help much in the case that you get a frame rate drop and FixedUpdate runs twice between Updates. Could introduce unusual bugs.
     
    Joe-Censored and PraetorBlue like this.
  18. LudiKha

    LudiKha

    Joined:
    Feb 15, 2014
    Posts:
    139
    I finally figured out a way to do this, I found a great way to do just this using ECS:

    Code (CSharp):
    1.       var playerLoop = PlayerLoop.GetCurrentPlayerLoop();
    2.       var world = World.DefaultGameObjectInjectionWorld;
    3.       var lateFixedUpdateGroup = world.GetExistingSystem<LateFixedUpdateSystemGroup>();
    4.       if (lateFixedUpdateGroup != null)
    5.         ScriptBehaviourUpdateOrder.AppendSystemToPlayerLoopList(lateFixedUpdateGroup, ref playerLoop, typeof(FixedUpdate));
    6.       PlayerLoop.SetPlayerLoop(playerLoop);
    As you can see, it's created a ComponentSystemGroup that hooks in to the FixedUpdate PlayerLoop (that one usually isn't there). This calls the same method ECS does to set up its default systems.

    upload_2021-2-10_19-23-22.png
    Note: the FixedUpdate callback is not there by default, and appears by hooking into it.

    If you want to do this without ECS, you can either dig into ScriptBehaviourUpdateOrder and see how they use the PlayerLoop API, or use a library such as UniTask for callbacks. The PlayerLoop API is powerful enough that you can hook into sub system callbacks, such as `FixedUpdate.DirectorFixedUpdatePostPhysics`

    When working with the PlayerLoop, you may want to look at this excellent debugger.

    https://gist.github.com/LotteMakesStuff/8534e01043826754344a570a4cf21002
     
    trombonaut likes this.