Higor
08-15-2012, 02:38 AM
The following post is a quote of a concept I introduced in another community a long time ago:
I've been looking at the code and spectating in first person mode lately.
As you have seen, when spectating, rotation is not replicated from server in a precise way, explanation below.
Rotator is made up of 3 integer components named Pitch, Yaw, Roll.
Though they can have any value any 32 bit signed integer have, there are only 65536 unique operational values for each
component, (65536 = 0 in terms of orientation and so on).
When transmitting rotators through Unreal's replication system, the components are compressed ( [>> 8], then [& 0xFF] ) into
8 bit unsigned integers, which go from 0 to 255 (256 combinations).
The main purpose of this was to obviously save bandwidth by converting a 12 byte struct into a 3 byte one, at the expense of
precision.
Ok, then how do our shots hit where we're aiming at if rotation is compressed during transmission?
Simple, view components are not transmitted client to server as a URotator struct, but instead as one 4 byte integer
containing both Pitch and Yaw ranging 0-65535 (2 byte integers compressed into a 4 byte INT).
What can we figure out about this?
Unlike other clients and spectators, the server actually knows where players are aiming at, with full precision.
Is it possible to increase view precision?
No, it is all hardcoded and obvously modifying all player pawns like UTPure did just for this is unnecessary work and
problems.
How can it be done then?
A Client-Server simulator belonging to the spectator, the spectator will be spectating the simulator instead of the player,
while the simulator will get accurate ViewRotation updates from the server.
Explaining the concept a little further:
When a spectator types a mutate command to spectate a certain player, a simulator is spawned and attached to the view
target.
Simulator will have the exact same ViewRotation (rotator struct), health and other non-replicated things as the spectated
player, explained later.
Simulator is hidden ingame (bHidden = true), so simulator won't be replicated to clients.
Simulator's owner is the spectator, meaning only the spectator will receive clientside updates.
When the spectator switches to another viewtarget, simulator is destroyed both clientside and serverside, ending the
bandwidth channel.
Simulator will know things not transmitted by the server as ammo count, armor.
With some intrusive processing, the server can use an input grabber from the player's prespective, this one will be enabled
if somebody is speccing him, good to catch input signals.
Since the spectator will be spectating the simulator instead of the actual player, the simulator will try to emulate (only)
clientside weapon firing, armor amount, full weapont list and ammocount without interfering with anything serverside.
With some extra work, it would be possible to display on the screen extra information the player might have transmitted to
the server and clients aren't getting.
I've been looking at the code and spectating in first person mode lately.
As you have seen, when spectating, rotation is not replicated from server in a precise way, explanation below.
Rotator is made up of 3 integer components named Pitch, Yaw, Roll.
Though they can have any value any 32 bit signed integer have, there are only 65536 unique operational values for each
component, (65536 = 0 in terms of orientation and so on).
When transmitting rotators through Unreal's replication system, the components are compressed ( [>> 8], then [& 0xFF] ) into
8 bit unsigned integers, which go from 0 to 255 (256 combinations).
The main purpose of this was to obviously save bandwidth by converting a 12 byte struct into a 3 byte one, at the expense of
precision.
Ok, then how do our shots hit where we're aiming at if rotation is compressed during transmission?
Simple, view components are not transmitted client to server as a URotator struct, but instead as one 4 byte integer
containing both Pitch and Yaw ranging 0-65535 (2 byte integers compressed into a 4 byte INT).
What can we figure out about this?
Unlike other clients and spectators, the server actually knows where players are aiming at, with full precision.
Is it possible to increase view precision?
No, it is all hardcoded and obvously modifying all player pawns like UTPure did just for this is unnecessary work and
problems.
How can it be done then?
A Client-Server simulator belonging to the spectator, the spectator will be spectating the simulator instead of the player,
while the simulator will get accurate ViewRotation updates from the server.
Explaining the concept a little further:
When a spectator types a mutate command to spectate a certain player, a simulator is spawned and attached to the view
target.
Simulator will have the exact same ViewRotation (rotator struct), health and other non-replicated things as the spectated
player, explained later.
Simulator is hidden ingame (bHidden = true), so simulator won't be replicated to clients.
Simulator's owner is the spectator, meaning only the spectator will receive clientside updates.
When the spectator switches to another viewtarget, simulator is destroyed both clientside and serverside, ending the
bandwidth channel.
Simulator will know things not transmitted by the server as ammo count, armor.
With some intrusive processing, the server can use an input grabber from the player's prespective, this one will be enabled
if somebody is speccing him, good to catch input signals.
Since the spectator will be spectating the simulator instead of the actual player, the simulator will try to emulate (only)
clientside weapon firing, armor amount, full weapont list and ammocount without interfering with anything serverside.
With some extra work, it would be possible to display on the screen extra information the player might have transmitted to
the server and clients aren't getting.