Hello @50berry, discrete actions are ofcourse often needed in games but they are problematic when it comes to a forward predicted networking solution so if you can design around it that’s the “best” approach.
For a Rocket League like implementation the jump should be quite straight forward though you should not need any special logic around it. Apply the jump impulse based on a jump input and the autonomous proxy will apply that jump on the same frame as the server applies it on and they should stay in sync.
When it comes to simulated proxies they will jump when they receive the input to jump, which happens on the wrong frame and they will then desync which triggers a resim which goes back in time corrects them and the replay physics and applies the jump on the correct frame.
After the resim they will get corrected in the air via render interpolation which could look a bit awkward but they should generally just move upwards a bit faster since in vehicle games, like Rocket League sim-proxy vehicles are most often forward predicted almost 100% so you can reliably interact with them at high speed. So when sim-proxies jump they are most likely in the correct XY location but wrong Z (height) location essentially so the main correction happens along Z.
If you do a character instead of a vehicle then balancing is generally a bit different, you should not have them 100% forward predicted because characters tend to act much more instant than a vehicle which has acceleration and steering to adhere to. A character can turn on a dime and stop anytime from full speed without deceleration. If you have a character 100% forward predicted and they stop then they need a large XY correction, meaning they need to slide backwards to correct the stopping point. Which I showed in the talk at UnrealFest.
Currently the best way to approach how forward predicted something is, is via InputDecay, so your input decay should be much more aggressive for a character compared to for a vehicle. Depending on how your character acts, if it has proper momentum you might not need to be as aggressive.
When it comes to jumping with a character (which is maybe 50% forward predicted) there is a larger issue because input decay works on inputs, and generally when jumping your inputs doesn’t control your movement anymore or they control much less of you movement. Meaning input decay can’t keep the sim-proxy at 50% forward prediction and the resimulation that happens as a result of jumping at the incorrect time will simulate the character physics object along its trajectory without limiting the forward prediction and the character ends up in the air 100% forward predicted. And depending on your latency the sim-proxy might be halfway or further into the jump after that first resimulation. Making render interpolation move the character forward and slightly up and you don’t actually see the jump.
So instead of input decay I’ve made a new type of solution to control how much forward predicted an object should be, which i call “Simulation Decay” and it controls how much of the physics acceleration / velocity integration gets applied onto the physics particles position and rotation during physics integration (before the solver moves on with the evolution from there).
That means that you can apply 100% of the input but the physics object will not move from 100% of the accelerations / velocities applied to it. But the velocities are unaltered, so you don’t lose any gravity or applied forces etc. the object just moves a bit slower through the simulation.
This is hard to describe without proper visualization and description, my goal is to write another tutorial for 5.8 about a lot of the different fundamentals around networked physics and hopefully I can do a talk about it also this year.
We don’t use the simulation decay yet anywhere, I was hoping on using it for the Fall Guys: Crown Jam game we released earlier this year which was using networked physics resimulation, but instead when a sim-proxy jump in that game we switch the replication mode to Predictive Interpolation which is a bit of a hacky way of making the same thing happen while in air since that replication mode runs in the “interpolated timeline” so not fully forward predicted..
When it comes to finding if you are grounded, you could rely on game thread traces and marshal the bIsGrounded bool to physics thread but it’s recommended to do everything that can affect your characters state on the physics thread so there are ways of tracing on the physics thread, though they are limited and it’s easy to do things that are not thread-safe. But there is implementations of it in the Chaos Mover plugin for example. UE.ChaosMover.Utils.FloorSweep_Internal is a funtion that uses physics thread trace.
The trace call itself is here: Chaos::Private::FGenericPhysicsInterface_Internal::SpherecastMulti();