Concept: Replication and Recycling
Pooling a replicated actor is a genuinely different problem from pooling a cosmetic one, because replication is built around actors being created and destroyed. A pooled actor is neither. Everything difficult follows from that one fact.
A client sees a teleport, not an appearance
A client builds its copy of an actor when the actor is spawned, and tears it down when it is destroyed. A recycled actor is never spawned a second time, so the client's copy simply moves and becomes visible again. Anything the client needs to know must arrive as an ordinary replicated property, because there is no second creation to carry it.
Why COND_InitialOnly is a trap
COND_InitialOnly sends a property only in the actor's first bunch - the initial burst of data when its channel opens. That is a sensible optimisation for an actor that is created, used and destroyed.
A pooled actor's channel is already open the second time it is used. The condition is satisfied and skipped, the property is never resent, and clients go on acting on the first use's data. Nothing errors and nothing logs. This is why it is called out everywhere in this documentation: it is the failure most likely to reach production.
Why a use can be skipped entirely
Replication is state-based, not event-based. It sends what a property is, not the fact that it changed. If an actor is recycled and reactivated with identical values before a client processes the update, the client sees one state, not two - the intermediate use never existed as far as it is concerned.
The mitigation is to make consecutive uses impossible to confuse: a monotonic counter inside the activation struct means two uses are never byte-identical, so the property is always dirty even when everything else about the two uses matches.
Why dormancy is not optional
A released actor is hidden and non-colliding. The engine treats exactly that combination as not relevant to anyone - a reasonable rule, since such an actor is usually genuinely irrelevant.
The consequence for a pool is severe. After a few seconds of irrelevance the actor's channel closes, and a channel closed for relevancy makes every client destroy its copy. The next acquire then has to recreate the actor on every client - which is precisely the cost the pool exists to eliminate.
Net dormancy closes the channel for a different reason, and a channel closed for dormancy leaves the client's copy intact. That is why Use Net Dormancy While Pooled defaults to on and why the pool warns if you disable it for a class that replicates.
Why acquire and release are server-only
Whether an actor is in use is authoritative gameplay state. A client that decided for itself would diverge immediately, and a client that released an actor the server still considers live would hand the same instance to two users. So the pool refuses both calls on a client for any replicating class - and leaves clients free to pool their own non-replicated effects, where the question does not arise.
See also
- How-To: Pool a Replicated Actor
- Concept: The Reuse Contract