FVector_NetQuantize100 larger than FVector

Hey, I’m trying to compress some data for networking. I’m just about playing around with the FVector_NetQuantize100 to see the gain of the compression. Unfortunately the resulting binary is bigger than the binary of FVector.



void ACompressionTest::BeginPlay()
{
    Super::BeginPlay();

    bool returnValue;
    TArray<uint8> binary;
    FMemoryWriter writer = FMemoryWriter(binary);
    FVector vector;
    writer << vector;
    UE_LOG(LogTemp, Error, TEXT("SizeOfVector: %d Bytes"), binary.Num()); // Num = 12

    TArray<uint8> binary2;
    FMemoryWriter writer2 = FMemoryWriter(binary2);
    FVector_NetQuantize100 vector100;
    vector100.NetSerialize(writer2, nullptr, returnValue);
    UE_LOG(LogTemp, Error, TEXT("SizeOfNetQuantize100: %d Bytes"), binary2.Num()); // Num = 16
}

As expected, the binary of FVector is 12 Bytes, as it consists of 3 floats that are 4 Bytes each. I would assume to get less bytes with FVector_NetQuantize100, but the result of the FVector_NetQuantize100´::NetSerialize was 16 Bytes. Am I doing something wrong?

Using UE 4.16

Right now you aren’t initializing your vectors to anything, so at best they’re all 0, or at worst, they’re NANs/MAX_FLOAT which could be throwing off the quantize since it bases how many bits to write out per component based on the Log2 of the highest component.

Try setting your vector to a “real” number (e.g. FVector TestVector(100.00, 200.0f, 300.0f) ) and see if that changes the numbers around.

Thanks @ExtraLifeMatt, did not think about that. Unfortunately it did not do it. Still 16 Bytes for FVector_NetQantize100.


    bool returnValue;
    TArray<uint8> binary;
    FMemoryWriter writer = FMemoryWriter(binary);
    FVector vector(100.f);
    writer << vector;
    UE_LOG(LogTemp, Error, TEXT("SizeOfVector: %d Bytes"), binary.Num());

    TArray<uint8> binary2;
    FMemoryWriter writer2 = FMemoryWriter(binary2);
    FVector_NetQuantize100 vector100 = FVector_NetQuantize100(FVector(100.f));
    vector100.NetSerialize(writer2, nullptr, returnValue);
    UE_LOG(LogTemp, Error, TEXT("SizeOfNetQuantize100: %d Bytes"), binary2.Num());

Serialization of FVector_NetQuanitze100 happens in NetSerialize. It mainly calls SerializePackedVector<100, 30> which uses Read/WritePackedVector<100, 30> depending on Ar.IsSaving(). In WritePackedVector there are four calls to Ar.SerializeInt(). SerializeInt is virtual so the behaviour also depends on the type of archive actually being used. In your case this is FMemoryWriter which derives from FMemoryArchive which again derives from FArchive. Neither FMemoryWriter nor FMemoryArchive actually overrides SerializeInt so the base FArchive implementation is used which calls ByteOrderSerialize, which in turn calls Serialize. Serialize is another virtual function and this time it is actually overridden by FMemoryWriter. Eventually for each SerializeInt call, FMemoryWriter needs sizeof(uint32&) bytes added to the Bytes array if it wasn’t large enough already. This explains the 16 bytes you’ve observed in your tests. Try another type of writer (e.g. FBitWriter along with GetNumBits) and see what the difference is.

Thanks @UnrealEverything. Crazy structure. Made a struct with NetSerializer and replicated it. Placed a breakpoint in NetSerialize and the Debugger showed me that Unreal uses FNetBitWriter (which is a child of FBitWriter) for net serialization. Had a go with that.



    bool returnValue;
    TArray<uint8> binary;
    FMemoryWriter writer = FMemoryWriter(binary);
    FVector vector(100.f);
    writer << vector;
    UE_LOG(LogTemp, Error, TEXT("SizeOfVector: %d Bytes"), binary.Num()); // 12 Bytes


    FNetBitWriter writer2 = FNetBitWriter(1000000); // init with max bits
    FVector_NetQuantize vector100 = FVector_NetQuantize(FVector(100.f)); 
    vector100.NetSerialize(writer2, nullptr, returnValue);
    UE_LOG(LogTemp, Error, TEXT("SizeOfNetQuantize100: %d bits"), writer2.GetNumBits()); // 28 Bits == 3,5 Bytes


Pretty good results. Thanks for your help guys.

Edit: Noticed I used FVector_NetQuantize in this test, NOT FVector_NetQuantize100.