Take the wheel physics off the PhysObj interface where the entity can answer - #336
Open
Sycatle wants to merge 1 commit into
Open
Take the wheel physics off the PhysObj interface where the entity can answer#336Sycatle wants to merge 1 commit into
Sycatle wants to merge 1 commit into
Conversation
… answer Three of the four PhysObj calls in DoPhysics now go through their entity-side equivalent. Each substitution was measured on a live vehicle at arbitrary angles rather than derived, and the angular velocity and world mass centre are hoisted into PhysicsSimulate so the four wheels share one lookup instead of taking four each. CalculateForceOffset is left alone: it returns an impulse, so the torque through the inertia tensor including its coupling, and it is the call that applies force to the wheels. On eight vehicles, GameFrame drops from 26.01 to 13.88 ms per frame.
This was referenced Aug 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses the measurements in #335, where a
PhysObjaccess is shown to cost 90-175 us against 0.2 us for the entity-side call, andDoPhysicsperforms four of them per wheel per substep.Three of the four are replaced. The fourth is deliberately left alone.
The substitutions
Each was measured on a live vehicle at arbitrary angles rather than derived from the docs:
phys:LocalToWorld( v )ent:LocalToWorld( v )phys:WorldToLocal( p )ent:WorldToLocal( p )phys:GetVelocityAtPoint( p )velocity + angVel x ( p - masscentre )There is no mass-centre offset to apply to the first two: the physics object local frame coincides with the entity one. That was my working assumption going in and it was wrong — applying it introduced 12 units of error everywhere.
The velocity form needs the angular velocity and the world mass centre. Both are derived once per substep in
PhysicsSimulate, which already holds the physics object, and read by all four wheels. That trades sixteen accesses per vehicle per substep for one.What is not replaced, and why
CalculateForceOffsetstays. It returns an impulse — the torque divided by the inertia tensor including its coupling — not a plain cross product. Measured per-component ratios of 44.8 / 30.0 / 26.5 do not follow the inertia 1882 / 1702 / 301, so it is not a component-wise division and I could not reproduce it reliably.It is also the call that applies force to the wheels. Reconstructing it slightly wrong would change how vehicles handle with nothing visibly broken, which is not a risk worth the last quarter of the gain.
Result
Eight vehicles, 413 frames each, same map and same player before and after, with every other local change identical in both arms:
CServerGameDLL::GameFrameI am deliberately not quoting a fleet-wide tick rate: the figure I have for that also includes a separate change slowing
Thinkfor parked vehicles, and attributing it here would overstate this patch.Evidence that handling is unchanged
Trajectories were recorded tick by tick over a fixed 13-second input programme, three runs before and three after. The before/after deviation stays inside the same envelope as two runs of identical code — at worst 0.20 units of position over 430 ticks, with final positions agreeing to three decimals.
Bit-identical reproduction does not exist here, so "within the noise of the unmodified build" is the criterion, with the noise measured rather than assumed. It has also been driven in game.
Known issues
The change was developed and measured in a fork of this addon; what is proposed here is a clean port of it, differing only in identifier names and comments. The measurements above come from that fork, not from this branch.