Just updated to 4.11 and having quite a few problems carrying over network code from 4.10. I realize that 4.11 is in Preview, but this issue also existed in 4.10 with some properties as well (Such as ‘Owner’ and ‘RemoteRole’ for example).
I have a projectile class which inherits from AActor. In the interests of keeping it as lightweight as possible (essential for a large volume of objects that update quickly over a network!), I have overriden some of the functions in AActor and am trying to avoid replicating properties that I don’t need. There is a huge opportunity for me to regain some bandwidth here. Unfortunately, more and more of these properties are becoming private and it’s becoming a pain to override the stock Actor replication and use your own, or tell properties that you know you will never need to not replicate.
The DOREPLIFETIME and DOREPLIFETIME_ACTIVE_OVERRIDE macros do NOT allow you to access private members of the AActor class - so some properties are forced to replicate whether you want them to or not! For my Ordnance class I have a custom SendInitialReplication function to handle the properties that I need, and all other parameters can be determined from these on the other side (such as Owner, Instigator etc). In order to do this, you have to override GetLifetimeReplicatedProps() and do NOT call ‘Super’. For example:
void ABZGame_Ordnance::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const
{
// Don't Call Super - Get Replicated Props from Blueprint class.
UBlueprintGeneratedClass* BPClass = Cast<UBlueprintGeneratedClass>(GetClass());
if (BPClass != nullptr)
{
BPClass->GetLifetimeBlueprintReplicationList(OutLifetimeProps);
}
// Now Replicate the ONLY two properties from AActor that we actually need!
DOREPLIFETIME(AActor, bTearOff);
DOREPLIFETIME(AActor, AttachmentReplication); // TODO - Only when Necessary / when this projectile is a 'Sticky' one.
DOREPLIFETIME(ABZGame_Ordnance, OwningWeapon); // Used to Determine if used with Caching and determine Instigator / Owner etc. No point copying three pointers pointing to the same thing!
DOREPLIFETIME(ABZGame_Ordnance, bExploded);
DOREPLIFETIME(ABZGame_Ordnance, bOrdnanceActive);
DOREPLIFETIME_CONDITION(ABZGame_Ordnance, OrdnanceReplicatedMovement, COND_SimulatedOrPhysics);
}
You can see from the comments why I have made these optimizations. If I decide I want to replicate ‘Owner’ however (from AActor) - I can’t without calling Super. DOREPLIFETIME(AActor, Owner) throws a compiler error.
I could just call Super of course, but then ALL properties from AActor that are set to replicate will also replicate when I don’t want them too. I CANNOT however override PreReplication() and use DOREPLIFETIME_ACTIVE_OVERRIDE(AActor, RemoteRole, false) for example, because RemoteRole is private and the macro can’t access it. I also get use ‘GetRemoteRole()’ or ‘GetOwner()’ either.
My Projectile works similarly to UT’s one. It has a custom Replication struct and a few minor properties and that’s ALL it needs. To correctly replicate the movement, I have also overriden GatherCurrentMovement() - but as of 4.11 AttachmentReplication is now private so I can’t modify that either, even with the accessor function
void ABZGame_Ordnance::GatherCurrentMovement()
{
if (RootComponent != nullptr)
{
// If attached, replicate only attachment position!
if (RootComponent->AttachParent != nullptr)
{
if (AttachmentReplication.AttachParent != nullptr)
{
AttachmentReplication.LocationOffset = RootComponent->RelativeLocation;
AttachmentReplication.RotationOffset = RootComponent->RelativeRotation;
AttachmentReplication.RelativeScale3D = RootComponent->RelativeScale3D;
}
}
else
{
OrdnanceReplicatedMovement.Location = RootComponent->GetComponentLocation();
OrdnanceReplicatedMovement.Rotation = RootComponent->GetComponentRotation();
OrdnanceReplicatedMovement.LinearVelocity = GetVelocity();
}
}
}
I’m all for encapsulation, but this is in my opinion yet another nail in the coffin for Multiplayer - which is becoming an increasingly overlooked topic with every release.