Skip to content

Make tick smoothers multithreaded - #990

Merged
FirstGearGames merged 10 commits into
FirstGearGames:mainfrom
belplaton:Make-Tick-Smoothers-multithreaded
Jan 23, 2026
Merged

FirstGearGames merged 10 commits into
FirstGearGames:mainfrom
belplaton:Make-Tick-Smoothers-multithreaded

Conversation

@belplaton

Copy link
Copy Markdown
Contributor

Tick Smoothing: execution refactor (single-thread -> jobified)

This PR changes how the existing tick smoothing runs: from per-object, main-thread execution to a centralized jobified pipeline in TickSmoothingManager. The core smoothing idea remains the same; the implementation/dispatch model is different.

Key differences (before vs after)

  • Before: each TickSmootherController subscribed to TimeManager and ran smoothing on the main thread.
    After: the controller only Register/Unregisters; all event wiring (OnUpdate/OnPreTick/OnPostTick, RTT, prediction replay) and execution are handled in TickSmoothingManager.

  • Before: per-object state lived in controller/smoother instances.
    After: state is stored in the manager as indexed Native/SoA containers (masks like canSmooth/useOwner/objectReconciling/..., realtime interpolation/multipliers, move-rates, snapshots, and a per-index TickTransformProperties queue).

  • Multithreading approach: work is expressed as explicit job chains with JobHandle dependencies (no per-object main-thread loops).

    • Transform work uses IJobParallelForTransform over TransformAccessArray (_graphicalTaa, _targetTaa, _trackerTaa).
    • Non-transform work uses IJobParallelFor with batching (ComputeBatchSize based on JobsUtility.JobWorkerCount).
  • Dispatch pattern: “payload + executeMask”. Jobs populate payload arrays (move, discard, set rates, snap, teleport, enqueue/clear, replay modify), and subsequent jobs apply only entries where executeMask != 0.

  • Tick buffer: the per-object tick buffer is now job-friendly via StripedRingQueue<TickTransformProperties> (one ring queue per index/stripe). Queue trimming (limits + required headroom over interpolation) is performed in DiscardExcessive... as part of job chains.

Phase breakdown (job chains)

  • OnPreTick

    • Update fast masks on main thread
    • PreTickMarkJob → discard → teleport (and queue clear) → PreTickCaptureGraphicalJobComplete()
  • OnPostTick

    • CaptureLocalTargetJobPostTickCaptureTrackerJobPostTickJob (produces snap/enqueue payloads)
    • discard → snap → add/enqueue → Complete()
  • OnUpdate

    • UpdateJob (move payload) → MoveToTargetJob (moves graphical; may trigger set rates/multiplier/clear) → Complete()
  • RTT / prediction replay

    • Separate job chains update realtime interpolation and perform ModifyTransformProperties after prediction replay.

Additional changes

  • Added MovementSettings.UseLocalSpace to select local/world space for position/rotation smoothing.
  • Updated .asmdef dependencies for Jobs/Burst/Mathematics/Collections.

@FirstGearGames

Copy link
Copy Markdown
Owner

I'd like to get this in but given the significant amount of change and complexity I do not want to merge this over official files. There's not enough dev time to move-around to verify/maintain all of these changes.

As mentioned via DM though, I still do want to see this in so you can benefit from them, as well anyone else that wishes to try these changes out. We talked about wrapping everything in a define.

Can you wrap the original files in a preprocessors please
#if !THREADED_TICKSMOOTHERS
//original file here
#endif

then make a new file for each you modified in a subfolder... eg:

FishNet/Components/Smoothing/TickSmoother.cs //original
FishNet/Components/Smoothing/Threaded/TickSmoother.cs //yours.

and in your files wrap in the preprocessors
#if THREADED_TICKSMOOTHERS
//your file here.
#endif

@belplaton

Copy link
Copy Markdown
Contributor Author

All done, I guess @FirstGearGames

@FirstGearGames
FirstGearGames merged commit 970afcf into FirstGearGames:main Jan 23, 2026
@FirstGearGames

Copy link
Copy Markdown
Owner

merged!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants