Skip to content

NetworkTransform.GetChanged incorrectly defines delta #1016

@oleg-pshenin

Description

@oleg-pshenin

Unity version.
6000.0.66f1

Fish-Networking version.
4.6.20 Pro

Discord link where you troubleshot the issue.
https://discord.com/channels/424284635074134018/1034477094731784302/1469296146181656708

Description
NetworkTransform has issue in GetChanged method. It defines changed state on comparison of current transform state with _lastSentTransformData, including fields that are not Serialized. It leads to NetworkTransform constant streaming even if nothing actually changed.

Examples:

  1. If you have NetworkTransform with SynchronizePosition only and keep it static, it will send updates every tick because localScale of 1,1,1 will compare to _lastSentTransformData.Scale of 0,0,0
  2. If you have NetworkTransform with None synchronization, it will still send packets with metadata only either every tick how explained in example 1 or when transform state doesn't match of the whole default data of _lastSentTransformData.

Replication
Have any NetworkTransform on the scene with disabled Synchronize Scale
Launch server or server+client
Launch client.
Track on client for _networkTransform.OnDataReceived += DataReceivedHandler; - it will be equal to tick rate
On server, GetChange will return ChangedDelta.ScaleXYZ always.

Expected behavior
GetChanged method should check for respected properties only if they are set to serialize, otherwise it leads to assymetry in comparison between transform state and what actually sent

Supposed fix (adding if checks for properties) that fixed constant "dirtyness" for me (not sure about parent logic):

        private ChangedDelta GetChanged(Vector3 lastPosition, Quaternion lastRotation, Vector3 lastScale, NetworkBehaviour lastParentBehaviour)
        {
            ChangedDelta changed = ChangedDelta.Unset;
            Transform t = _cachedTransform;

            if (_synchronizePosition)
            {
                Vector3 position = t.localPosition;
                if (Mathf.Abs(position.x - lastPosition.x) >= _positionSensitivity)
                    changed |= ChangedDelta.PositionX;
                if (Mathf.Abs(position.y - lastPosition.y) >= _positionSensitivity)
                    changed |= ChangedDelta.PositionY;
                if (Mathf.Abs(position.z - lastPosition.z) >= _positionSensitivity)
                    changed |= ChangedDelta.PositionZ;
            }

            if (_synchronizeRotation)
            {
                Quaternion rotation = t.localRotation;
                if (!rotation.Matches(lastRotation, true))
                    changed |= ChangedDelta.Rotation;
            }

            ChangedDelta startChanged = changed;

            if (_synchronizeScale)
            {
                Vector3 scale = t.localScale;
                if (Mathf.Abs(scale.x - lastScale.x) >= _scaleSensitivity)
                    changed |= ChangedDelta.ScaleX;
                if (Mathf.Abs(scale.y - lastScale.y) >= _scaleSensitivity)
                    changed |= ChangedDelta.ScaleY;
                if (Mathf.Abs(scale.z - lastScale.z) >= _scaleSensitivity)
                    changed |= ChangedDelta.ScaleZ;
            }

            if (_synchronizeParent)
            {
                if (changed != ChangedDelta.Unset && ParentBehaviour != null)
                    changed |= ChangedDelta.Nested;
            }

            //If added scale or childed then also add extended.
            if (startChanged != changed)
                changed |= ChangedDelta.Extended;

            return changed;
        }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions