You can replicate entire structs if their properties are marked as UPROPERTY().
Simplified example from ShooterGame:
/** replicated information on a hit we've taken */
USTRUCT()
struct FTakeHitInfo
{
GENERATED_USTRUCT_BODY()
UPROPERTY()
float ActualDamage;
/** The damage type we were hit with. */
UPROPERTY()
UClass* DamageTypeClass;
UPROPERTY()
TWeakObjectPtr<class AShipPawn> PawnInstigator;
/** Specifies which DamageEvent below describes the damage received. */
UPROPERTY()
int32 DamageEventClassID;
UPROPERTY()
uint32 bKilled : 1;
private:
/** A rolling counter used to ensure the struct is dirty and will replicate. */
UPROPERTY()
uint8 EnsureReplicationByte;
/** Describes general damage. */
UPROPERTY()
FDamageEvent GeneralDamageEvent;
public:
FTakeHitInfo()
: ActualDamage(0)
, DamageTypeClass(NULL)
, PawnInstigator(NULL)
, DamageEventClassID(0)
, bKilled(false)
, EnsureReplicationByte(0)
{}
FDamageEvent& GetDamageEvent()
{
if (GeneralDamageEvent.DamageTypeClass == NULL)
{
GeneralDamageEvent.DamageTypeClass = DamageTypeClass ? DamageTypeClass : UDamageType::StaticClass();
}
return GeneralDamageEvent;
}
void EnsureReplication()
{
EnsureReplicationByte++;
}
};
class AMyPawn : public APawn
{
...
UPROPERTY(Transient, ReplicatedUsing = OnRep_LastTakeHitInfo)
struct FTakeHitInfo LastTakeHitInfo;
...
}
void AMyPawn::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION(AMyPawn, LastTakeHitInfo, COND_OwnerOnly);
}