2,000 tickers: managers, subsystems, instancing

Mock Q6 part 3 (Partial: right pattern, didn't explain why it wins) · 6 min

In one breath

2,000 ticking actors cost scheduling, a call each and cache misses, and the actors themselves are expensive before they tick. A central dispatcher saves the scheduling. The real win is a manager that does the work itself in a tight loop over plain data, lives in a tickable world subsystem, and draws with instancing. At huge scale, use Mass.

Why 2,000 individual ticks is worse

Your Game State dispatcher: what's good, what gets pushed on

GoodInterviewer push
One tick function instead of 2,000A broadcast still makes 2,000 Blueprint calls. You saved scheduling, not per-call cost
Everyone updates at one controllable point in the frameOrder between listeners isn't guaranteed
Objects subscribe only while they need updatesGame State is a gameplay/replication class, so using it for engine plumbing is a coupling smell. And binding to a BP Game State hard-references it (references)

The better versions

  1. Move the work into the manager: an array of structs (position, velocity), one C++ loop. That's cache friendly, with no calls out.
  2. Home it in a UTickableWorldSubsystem: world lifetime, no actor, no hard reference (GetWorld()->GetSubsystem<T>()), ticks itself.
  3. Don't have 2,000 actors: one manager owning instance data plus ISM/HISM for rendering.
  4. Very large counts: Mass Entity (entities, fragments, processors).
30-second answer

"Per-actor ticks each cost scheduling and a call, with bad cache locality, and 2,000 actors is expensive before they even tick. I've used a central dispatcher so objects only subscribe while they need updates. The better version moves the work into the manager: one tick in a tickable world subsystem, looping over a data array, with instanced rendering. At very large scale, Mass. It's the same idea as my plugin's cluster component: many shapes in one component."

Quiz yourself

Three reasons 2,000 ticking actors are slow.

Per-tick scheduling overhead, a call (and BP VM entry) per tick, scattered memory (cache misses). Plus the actors' own overhead.

What does a broadcast dispatcher save, and what doesn't it save?

Saves tick scheduling (one tick function). Doesn't save the per-listener call cost.

Where should a tick manager live, and why not Game State?

UTickableWorldSubsystem: world lifetime, no actor, no BP hard refs. Game State is for gameplay/replicated state, so using it here couples unrelated things.

What's ISM/HISM for?

Instanced Static Mesh (Hierarchical adds per-cluster culling/LOD): drawing many copies of a mesh in few draw calls, owned by one component.

How does this connect to your plugin?

The cluster component is one component owning many shapes instead of many components: the same "one owner, many items" idea.