This article is a collaboration with WizardCell and on it, you’ll learn how
DORM_Initial works and why you should be careful with it.
If we read the description of the
DORM_Initial dormancy setting, we see what follows:
This actor is initially dormant for all connection if it was placed in map.
Which made me understand that this setting would work like
DORM_DormantAll just with a couple extra optimizations. But it isn’t the case, let’s see what are the implications of using this setting.
When an Actor becomes relevant to a connection, all the properties of said Actor are sent to the connection, no matter whether the Actor is
DORM_Awake. That means that the state the client receives from the Actor will be consistent of what the server sees about it.
However, that is not the case of
DORM_Initial Actors, as they will not send any C++ replicated property if a connection becomes relevant:
Watch out! Blueprint replicated properties ignore Actor dormancy settings.
How to use
So shall I simply not use
DORM_Initial? No, you should!
DORM_Initial Actors won’t be considered for replication at all even under relevancy, and sometimes that can be a huge optimization.
To ensure incoming connections get the new values over
DORM_Initial Actors, you should call
FlushNetDormancy on them after updating their properties. This will make the Actor to become
DORM_DormantAll but only when strictly needed.
What about calling
ForceNetUpdate to also flush the dormancy?
Be very careful with this, as
ForceNetUpdate also calls
FlushNetDormancy but its guarded with a
So, if the
NetDriver is Null at the moment you call
ForceNetUpdate*, the Actor will never call
FlushNetDormancy, causing it to stay in a
DORM_Initial state. For that reason it is always recommended to explicitly call
FlushNetDormancy when dealing with
*Worlds don’t get a
UWorld::Listen is called.
Thanks for reading!
Let’s hope everything is clear! Feel free to reach us out if there are questions! And I encourage every reader to check WizardCell’s articles.