Skip to content

Conversation

@belplaton
Copy link
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
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

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