This article provides code examples for various replication concepts and tasks. If any example includes a defaultproperties block, keep in mind that default values are inherited from parent classes. Often you don't need to specify all of the values listed here.
Actor replication examples
The following are a few example class frames for various types of actor replication.
The ReplicationInfo (always replicate)
The class ReplicationInfo(RTNP, U1, UT, U2, U2XMP, UE2Runtime, UT2003, UT2004, UDK, UT3) already exists in all Unreal Engine games and contains the following relevant default values:
class ReplicationInfo extends Info abstract native; defaultproperties { RemoteRole=ROLE_SimulatedProxy bAlwaysRelevant=True }
RemoteRole=ROLE_SimulatedProxy
ensures that actors of this type participate in replication, while bAlwaysRelevant=True
ensures that actors of this type will be replicated to all clients, bypassing any relevance checks. The ReplicationInfo class itself is abstract, because creating instances of it wouldn't make sense - you should subclass it. ReplicationInfo is declared as native class for two reasons. One is that there are native subclasses, which is only allowed if the parent class is native as well.
The other reason is a special native handling of the bSkipActorPropertyReplication
for replication purposes. (That property is set to True
in ReplicationInfo's parent class Info.) If you look at the replication block of class Actor, you will notice that bSkipActorPropertyReplication
can be overridden by bNetInitial
, causing corresponding properties to be replicated at least once. The ReplicationInfo native code overrides this behavior and turns off even initial replication. Thus only replicated variables declared in subclasses will be replicated, even when sending the initial data. This makes ReplicationInfo more efficient for replication than other classes with the same default values.
Owner-only replication
Ensuring that an actor is only replicated to its owner can be achieved in multiple ways. An actor is always relevant to its owning client (i.e. the actor's owner must be the client's PlayerController/PlayerPawn, or the owner actor must be owned by the client), but only relevant to other clients under certain circumstances.
Invisible actors
If the actor is not supposed to be visible, owner-only replication can easily be achieved by hiding the actor:
defaultproperties { RemoteRole=ROLE_SimulatedProxy // or ROLE_DumbProxy or ROLE_AutonomousProxy bAlwaysRelevant=False // inherited from Actor, but keep in mind when inheriting from e.g. ReplicationInfo bHidden=True }
Visible actors
If the actor must be visible, but only to its owner, you can use the standard visibility settings for that purpose and at the same time replicate the actor only to its owning client:
defaultproperties { RemoteRole=ROLE_SimulatedProxy // or ROLE_DumbProxy or ROLE_AutonomousProxy bAlwaysRelevant=False // inherited from Actor, but keep in mind when inheriting from e.g. ReplicationInfo bOnlyOwnerSee=True }
Note that the reverse, bOwnerNoSee
won't prevent the actor from being replicated to its owner, because ownership is a stronger relevance criteria.
Regardless of visibility
Starting with Unreal Engine 2, replication can be limited to the owner without having to change rendering properties:
defaultproperties { RemoteRole=ROLE_SimulatedProxy // or ROLE_DumbProxy or ROLE_AutonomousProxy bAlwaysRelevant=False // inherited from Actor, but keep in mind when inheriting from e.g. ReplicationInfo bOnlyRelevantToOwner=True }
Since the actor still also exists serversidely, you will probably still use bOwnerNoSee
for the actor.
Replicate as if visible
In special cases you might want to replicate an invisible actor as if it was visible, i.e. only to clients that would be able to see the actor if it wasn't invisible. For example you might want to replicate a projectile, but handle its visibility entirely via a separate Emitter actor. In that case you cannot rely on bHidden, because it would prevent replication for all but the owning client:
defaultproperties { RemoteRole=ROLE_SimulatedProxy // or ROLE_DumbProxy or ROLE_AutonomousProxy bAlwaysRelevant=False // inherited from Actor, but keep in mind when inheriting from e.g. ReplicationInfo DrawType=DT_None }
Variable replication
This section describes various ways to replicate variable values.
Replicating all changes
Unreal Engine 1 and Unreal Engine 2:
replication { unreliable if (Role == ROLE_Authority) VariableToReplicate; }
Only Unreal Engine 2:
replication { unreliable if (True) VariableToReplicate; }
Unreal Engine 3:
replication { if (True) VariableToReplicate; }
Why just True
? Well, variables can only be replicated in one direction: From the server to the clients. On the server the expression Role == ROLE_Authority
always evaluates to True
, so there's no need to evaluate it every time.
Only the initial value
Often all changes of a value can be simulated by the client, as long as it knows the starting value. In that case it would be a waste of bandwidth to replicate additional serverside changes.
Unreal Engine 1 and Unreal Engine 2:
replication { unreliable if (Role == ROLE_Authority && bNetInitial) VariableToReplicate; }
Only Unreal Engine 2:
replication { unreliable if (bNetInitial) VariableToReplicate; }
Unreal Engine 3:
replication { if (bNetInitial) VariableToReplicate; }
From client to server
As mentioned above, variable values only replicate from the server to clients. For the other way, you need to use function replication to update the serverside value. But even then, replication is only possible from the owning client to the server. If the actor isn't owned by the sending client, the server will discard the replicated call or value.
Unreal Engine 1 can actually replicate values from the owning client to the server:
replication { unreliable if (Role != ROLE_Authority) // only works in Unreal Engine 1 and only for owning client! VariableToReplicate; }