Send Vectors as Rotators over network to halve bandwidth!?

Hello,

I was wondering if anyone could corroborate a test that I have done where I try to reduce outgoing network bandwidth by converting a Vector to a Rotator for the purpose of making the data sent less, and then converting back to Vector on the other side for use on the Remote.

If you check out this report from the Unreal networking profiling app you can see that for the same number of sends the Rotators are half the data compared to the Vector.
I am perplexed by this but am thinking maybe Unreal Quantizes rotators but not Vectors by default? Does anyone know if this is true?

I’m working mainly with Blueprints and I can’t find a way to control a specific variables network quantization using blueprints.

So I did a test where I converted a Vector that had many decimal numbers in its members, to a Rotator and then converted that again and put the result in a new vector, then printed out both the first vector and the last vector.
They both look the same at least up to the three decimal printed.

That would be enough precision for me, for my intended use of these variables.

(I haven’t yet done the full test and measurement with my method.)

Does anyone have any experience or thoughts if this sounds ok?
Or know how to control quantization in blueprints?

Cheers,

net_variables.png

vecNrotator.png

As far as I know, internally, rotators are handled as quaternions. It’s possible that they have some kind of compression or optimization to them, but you’d have to sift through the source to know for sure.

I just added this idea into the project and did a network test but unfortunately there’s problems.

If one of the Rotator members is negative, that member will on the Receiving remote have been changed. It then seems to be = 360-(abs(theMemberValue)).
So a -60 would be turned into a 300.

This is not happening if I just do a local test say in PIE. So something UE does to Rotators when replicating them.

I suppose I could try to make a Struct with a [Rotator+3 Bools] and use the bools to indicate if a value should be negative or not. (and do an abs() before sending).

If I’m calculating correct that would save me 2.6 bytes. 12-(6.4+3)
Not sure if that is going to be worth the hassle I’ll see.

It would be nice if there was another way to easily save some data there I might ask on the c++ section.

**EDIT: **Thinking about it I should be able to just use a single Byte instead of the three bools and have a rule where each combination of negative and positive members are represented by a specific value. Then I’m saving 4.6 bytes! :slight_smile:

I’ve read some stuff on the internet about bandwidth optimization, and some other replication settings in Unreal 4 give hints about this as well.

There is a setting to reduce the number of decimals to remove when broadcasting variables (when working with Float). I’m sure you can apply the same kind of logic to rotation and vectors.

You can even turn them into integers for testing purposes.

But I don’t know what impact it can have. I tried to think about the impact while writing this and did not come up with something relevant aside from “clunky rotation on clients”.

My case is that these are Location/Position values from the VR Motion Controllers that I want replicated ideally at the VR 90hz frequency.
I could go down in precision to say 1 decimals as that would still give me millimeter moves.
If I assume that the Player will have a max 10 meter side play space, 1000 units, then yes maybe I should be able to use a short style int of 2 bytes each.
But then I have to figure out how to do that in c++, which might not be too hard?

UPDATE: For anyone interested I managed to do this with some small bits of c++. Ideally it should have been possible to just use an int16 per member but it seemed that Unreal does not allow that. So I made a custom struct where each of the vector members was represented by two uint8’s. Then you can google how to turn an int16 into two uint8’s in c code.
So I ended up with a custom struct that gets replicated and two functions to convert a vector into and out of this struct.

It works a treat for my use case and saves a big bunch of data bandwidth. (I think the NetProfiler reports too small size for the struct though)