feat: NetworkTransform.compressRotation option. disabled by default to not break 2D projects.

This commit is contained in:
vis2k 2021-03-14 14:53:23 +08:00
parent 19017dfb41
commit 78b6cfbde7
5 changed files with 63 additions and 25 deletions

View File

@ -46,6 +46,10 @@ public abstract class NetworkTransformBase : NetworkBehaviour
[Tooltip("Changes to the transform must exceed these values to be transmitted on the network.")]
public float localScaleSensitivity = .01f;
[Header("Compression")]
[Tooltip("Enables smallest-three quaternion compression, which is lossy. Great for 3D, not great for 2D where minimal sprite rotations would look wobbly.")]
public bool compressRotation; // disabled by default to not break 2D projects
// target transform to sync. can be on a child.
protected abstract Transform targetComponent { get; }
@ -73,24 +77,29 @@ public class DataPoint
// serialization is needed by OnSerialize and by manual sending from authority
// public only for tests
public static void SerializeIntoWriter(NetworkWriter writer, Vector3 position, Quaternion rotation, Vector3 scale)
public static void SerializeIntoWriter(NetworkWriter writer, Vector3 position, Quaternion rotation, Vector3 scale, bool compressRotation)
{
// serialize position, rotation, scale
// => compress rotation from 4*4=16 to 4 bytes
// => less bandwidth = better CCU tests / scale
writer.WriteVector3(position);
// use uncompressed quaternion for now.
// smallest three is only good for 3D games.
// in 2D, sprites would have tiny noticeable 'wonky' rotations to them.
// => need to make 2D rotations optional/selectable later!
writer.WriteQuaternion(rotation);
if (compressRotation)
{
// smalles three compression for 3D
writer.WriteUInt32(Compression.CompressQuaternion(rotation));
}
else
{
// uncompressed for 2D
writer.WriteQuaternion(rotation);
}
writer.WriteVector3(scale);
}
public override bool OnSerialize(NetworkWriter writer, bool initialState)
{
// use local position/rotation/scale for VR support
SerializeIntoWriter(writer, targetComponent.localPosition, targetComponent.localRotation, targetComponent.localScale);
SerializeIntoWriter(writer, targetComponent.localPosition, targetComponent.localRotation, targetComponent.localScale, compressRotation);
return true;
}
@ -116,11 +125,9 @@ void DeserializeFromReader(NetworkReader reader)
// deserialize position, rotation, scale
// (rotation is compressed)
localPosition = reader.ReadVector3(),
// use uncompressed quaternion for now.
// smallest three is only good for 3D games.
// in 2D, sprites would have tiny noticeable 'wonky' rotations to them.
// => need to make 2D rotations optional/selectable later!
localRotation = reader.ReadQuaternion(),
localRotation = compressRotation
? Compression.DecompressQuaternion(reader.ReadUInt32())
: reader.ReadQuaternion(),
localScale = reader.ReadVector3(),
timeStamp = Time.time
};
@ -352,7 +359,7 @@ void Update()
// local position/rotation for VR support
using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
{
SerializeIntoWriter(writer, targetComponent.localPosition, targetComponent.localRotation, targetComponent.localScale);
SerializeIntoWriter(writer, targetComponent.localPosition, targetComponent.localRotation, targetComponent.localScale, compressRotation);
// send to server
CmdClientToServerSync(writer.ToArraySegment());

View File

@ -57,6 +57,7 @@ MeshRenderer:
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@ -68,6 +69,7 @@ MeshRenderer:
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
@ -94,7 +96,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
sceneId: 0
serverOnly: 0
forceHidden: 0
visible: 0
m_AssetId:
hasSpawned: 0
--- !u!114 &3679374677650722848
@ -115,6 +117,7 @@ MonoBehaviour:
localPositionSensitivity: 0.01
localRotationSensitivity: 0.01
localScaleSensitivity: 0.01
compressRotation: 1
--- !u!114 &8309506939003697769
MonoBehaviour:
m_ObjectHideFlags: 0

View File

@ -57,6 +57,7 @@ MeshRenderer:
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@ -68,6 +69,7 @@ MeshRenderer:
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
@ -94,7 +96,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
sceneId: 0
serverOnly: 0
forceHidden: 0
visible: 0
m_AssetId:
hasSpawned: 0
--- !u!114 &644305951047116972
@ -130,3 +132,4 @@ MonoBehaviour:
localPositionSensitivity: 0.01
localRotationSensitivity: 0.01
localScaleSensitivity: 0.01
compressRotation: 1

View File

@ -53,6 +53,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
sceneId: 0
serverOnly: 0
visible: 0
m_AssetId:
hasSpawned: 0
--- !u!95 &2240606817507776182
@ -92,6 +93,7 @@ MonoBehaviour:
localPositionSensitivity: 0.01
localRotationSensitivity: 0.01
localScaleSensitivity: 0.01
compressRotation: 1
--- !u!195 &6900008319038825817
NavMeshAgent:
m_ObjectHideFlags: 0
@ -187,12 +189,14 @@ Light:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4426914200102054949}
m_Enabled: 1
serializedVersion: 8
serializedVersion: 10
m_Type: 0
m_Shape: 0
m_Color: {r: 1, g: 0.9205329, b: 0.7877358, a: 1}
m_Intensity: 3
m_Range: 15
m_SpotAngle: 80
m_InnerSpotAngle: 62.1886
m_CookieSize: 10
m_Shadows:
m_Type: 2
@ -202,6 +206,24 @@ Light:
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
m_CullingMatrixOverride:
e00: 1
e01: 0
e02: 0
e03: 0
e10: 0
e11: 1
e12: 0
e13: 0
e20: 0
e21: 0
e22: 1
e23: 0
e30: 0
e31: 0
e32: 0
e33: 1
m_UseCullingMatrixOverride: 0
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
@ -209,12 +231,15 @@ Light:
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingLayerMask: 1
m_Lightmapping: 4
m_LightShadowCasterMode: 0
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
m_UseBoundingSphereOverride: 0
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!1 &4730779867780281009
@ -258,6 +283,10 @@ PrefabInstance:
propertyPath: m_Name
value: 3D Model
objectReference: {fileID: 0}
- target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
propertyPath: m_RootOrder
value: 0
objectReference: {fileID: 0}
- target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
propertyPath: m_LocalPosition.x
value: 0
@ -270,6 +299,10 @@ PrefabInstance:
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
propertyPath: m_LocalRotation.x
value: 0
@ -282,14 +315,6 @@ PrefabInstance:
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
propertyPath: m_RootOrder
value: 0
objectReference: {fileID: 0}
- target: {fileID: 400010, guid: 38b49695fc0a4418bbc350f2366660c5, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0

View File

@ -14,7 +14,7 @@ public void SerializeIntoWriterTest()
Quaternion rotation = new Quaternion(0.1f, 0.2f, 0.3f, 0.4f);
Vector3 scale = new Vector3(0.5f, 0.6f, 0.7f);
NetworkTransformBase.SerializeIntoWriter(writer, position, rotation, scale);
NetworkTransformBase.SerializeIntoWriter(writer, position, rotation, scale, true);
NetworkReader reader = new NetworkReader(writer.ToArray());
Assert.That(reader.ReadVector3(), Is.EqualTo(position));
Assert.That(reader.ReadUInt32(), Is.EqualTo(Compression.CompressQuaternion(rotation)));