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

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?

I believe that FixedUpdate obeys the script execution order set up in the Editor

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.

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:

FixedUpdate 1
{
   Object 1
   {
      move
   }
   Object 2
   {
      move
   }
...
   Object 1
   {
      check if touches
   }
   Object 2
   {
      check if touches
   }
}

Adjusting the execution order will only grant me

Fixed Update 1
{
   Object 1
   {
      move
      check if touches
   }
   Object 2
   {
      move
      check if touches
   }
}

Suggestion: Make your own LateFixedUpdate! :slight_smile:

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: Unity - Manual: Script Execution Order settings

1 Like

yea so what i’m suggesting is you do something like this…

class Body : MonoBehaviour {
static List<Body> s_AllBodies = new List<Body>();
void OnEnable() { s_AllBodies.Add(this);}
void OnDisable() { for(;s_AllBodies.Remove(this););}
void move(){}
void check(){}
public static void Move() { foreach(var item in s_AllBodies) item.move(); }
public static void Check() { foreach(var item in s_AllBodies) item.check(); }
}
class PreLateUpdateRunner : MonoBehaviour { void FixedUpdate() { Body.Move();} }
class PostLateUpdateRunner : MonoBehaviour { void FixedUpdate() { Body.Check();} }

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?

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.

class Body : MonoBehaviour {
private readonly System.Action m_MoveCallback, m_CheckCallback;
public Body() { m_MoveCallback = this.PreFixedUpdate; m_CheckCallback = this.PostFixedUpdate; }
void OnEnable() { PreUpdateRunner.OnFixedUpdate += this.m_MoveCallback; PostUpdateRunner.OnFixedUpdate += this.m_CheckCallback; }
void OnDisable() { PreUpdateRunner.OnFixedUpdate -= this.m_MoveCallback; PostUpdateRunner.OnFixedUpdate -= this.m_CheckCallback; }

void PreFixedUpdate() {..}
void PostFixedUpdate() {..}
}
class PreUpdateRunner : MonoBehaviour {
public static event System.Action OnFixedUpdate;
void FixedUpdate() { var Callback = OnFixedUpdate; if(Callback!=null)Callback();}
}
class PostUpdateRunner : MonoBehaviour {
public static event System.Action OnFixedUpdate; 
void FixedUpdate() { var Callback = OnFixedUpdate; if(Callback!=null)Callback();} 
}

Its what Unity does under the hood for you. Makes you grateful to have an engine now, doesn’t it.

1 Like

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.

1 Like

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:

void FixedUpdate() {
Body.PreMove();
Body.Move();
Body.PostMove();
Body.Check();
Body.PostCheck();
}

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?

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?

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().

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?

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.

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.

Doesn’t help much in the case that you get a frame rate drop and FixedUpdate runs twice between Updates. Could introduce unusual bugs.

2 Likes

I finally figured out a way to do this, I found a great way to do just this using ECS:

      var playerLoop = PlayerLoop.GetCurrentPlayerLoop();
      var world = World.DefaultGameObjectInjectionWorld;
      var lateFixedUpdateGroup = world.GetExistingSystem<LateFixedUpdateSystemGroup>();
      if (lateFixedUpdateGroup != null)
        ScriptBehaviourUpdateOrder.AppendSystemToPlayerLoopList(lateFixedUpdateGroup, ref playerLoop, typeof(FixedUpdate));
      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.

6824717--792992--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.

2 Likes