Quaternions Are Not Covered by DOREP NEQs

Dear Friends At Epic,

I could compile using DOREPSTRUCT,

buuuut

I would have thought that since FVectors and FRotators work with DOREP that FQuat’s should do :slight_smile:

.h

UPROPERTY(Replicated)
FQuat WeaponFlipPitch_Speed;

.cpp

int32* AJoyWarriorBase::GetReplicationList(uint8* Recent, FPropertyRetirement* Retire, int32* Ptr, UPackageMap* Map, UActorChannel* Channel, FReplicationFlags RepFlags)
{
	Ptr = Super::GetReplicationList(Recent, Retire, Ptr, Map, Channel, RepFlags);
	
	DOREP(AJoyWarriorBase, WeaponFlipPitch_Speed);
	
	return Ptr;
}

Error:

1>------ Build started: Project: VictoryGame, Configuration: Development_Editor x64 ------
1>  JoyWarriorBase.cpp
1>E:\RocketVictory\VictoryGame\Source\VictoryGame\Private\Characters\JoyWarriorBase.cpp(1527): error C2665: 'NEQ' : none of the 20 overloads could convert all the argument types
1>          c:\program files\rocket\engine\intermediate\builddata\include\engine\../../../../Source/Runtime/Engine/Classes/Vehicles/WheeledVehicleMovementComponent.h(153): could be 'bool NEQ(const FReplicatedVehicleState &,const FReplicatedVehicleState &,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(74): or       'bool NEQ(uint8,uint8,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(75): or       'bool NEQ(int32,int32,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(76): or       'bool NEQ(uint64,uint64,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(77): or       'bool NEQ(uint32,uint32,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(78): or       'bool NEQ(float &,float &,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(79): or       'bool NEQ(FVector &,FVector &,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(82): or       'bool NEQ(FRotator &,FRotator &,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(84): or       'bool NEQ(const UObject *,const UObject *,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(89): or       'bool NEQ(FName &,FName,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(90): or       'bool NEQ(FColor &,FColor &,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(91): or       'bool NEQ(FLinearColor &,FLinearColor &,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(92): or       'bool NEQ(FText,FText,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(93): or       'bool NEQ(FPlane &,FPlane &,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(96): or       'bool NEQ(const FString &,const FString &,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(97): or       'bool NEQ(const FRigidBodyState &,const FRigidBodyState &,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(101): or       'bool NEQ(FVector2D &,FVector2D &,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(102): or       'bool NEQ(FGuid &,FGuid &,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(103): or       'bool NEQ(FRepMovement &,FRepMovement &,UPackageMap *,UActorChannel *)'
1>          C:\Program Files\Rocket\Engine\Source\Runtime\Engine\Public\Net/UnrealNetwork.h(109): or       'bool NEQ(FNetworkGUID &,FNetworkGUID &,UPackageMap *,UActorChannel *)'
1>          while trying to match the argument list '(FQuat, FQuat, UPackageMap *, UActorChannel *)'
1>  -------- End Detailed Actions Stats -----------------------------------------------------------
1>ERROR : UBT error : Failed to produce item:

#Follow Up

All is well, DOREPSTRUCT covers FQuat just fabulously

I was just confused as to why FVector and FRotator work with DOREP but not FQuat

would it be hard to add FQuat to the DOREP NEQs ?

Rama

Glad to see you’ve worked your issue out.

To answer your question I believe by default only the Vector and Rotator are replicated as these require significantly lower bandwidth due to the nature of how they are handled. The objective is to lose some accuracy in the replicated location and rotation in order to get the absolute maximum out of bandwidth (32 players in a game like UT3 or Gears after all would result in a very large quantity of actors requiring networking!)

Historically, an FVector would be replicated as a set of three signed integers (with a range of -1048576 to 1048576 - anything outside this range would be clamped) and an FRotator would be replicated as three unsigned bytes (giving an accuracy of approximately 1.4 degrees).

A quaternion probably does not compress as well as a rotator due to it’s nature - but even if it did, you’d still compress it down to four unsigned bytes, which is 33% more data to replicate each time that is not necessary to do, as you only care about replicating the actual rotation, Euler angle rotators work just fine. If you need to do any math with the rotation after replication, it is better to use a rotator for networking, and convert to a quaternion when required.

At present in your example, a quaternion is not compressed at all. I suspect that each component is a half precision float, meaning that instead of sending three bytes, you’d be sending forty-eight bytes - an increase of 1600%!

oooooh right!

I forgot that FVector and FRotator are getting that special treatment!

That explains it!

Also means I prefer to use DOREPSTRUCT for the accuracy.

Thanks Luke!

Rama