Skip to content

Conversation

NoelStephensUnity
Copy link
Collaborator

@NoelStephensUnity NoelStephensUnity commented Sep 9, 2025

Purpose of this PR

This PR resolves the issue where setting SwitchTransformSpaceWhenParented to true and then setting InLocalSpace to true will force the motion authority to continually send updates each tick (whether there is a delta or not).

Jira ticket

MTTB-1584

fix: #3653
fix: #3646
fix: #3645

Changelog

  • Added: NetworkRigidbody documentation section.
  • Fixed: NetworkTransform state synchronization issue when NetworkTransform.SwitchTransformSpaceWhenParented is enabled and the associated NetworkObject is parented multiple times in a single frame or within a couple of frames.
  • Fixed: Issue when spawning, parenting, and immediately re-parenting.
  • Changed: NetworkTransform now synchronizes NetworkTransform.SwitchTransformSpaceWhenParented when it is updated by the motion model authority.
  • Changed: NetworkObjects pending to be shown to clients can now occur on partial network ticks. If any pending NetworkObjects pending to be shown to clients happens to be ready on a new network tick they still are shown after network variable deltas have been processed.
  • Changed: The default NetworkDelivery used by all messages is now reliable fragmented sequenced with the exception of named, unnamed, and any messages sent with a user specified network delivery type. This assures certain order of operations to be preserved when same call-stack changes are applied to a newly spawned, authority side, NetworkObject.
  • Changed: NetworkTransform documentation to better reflect the Teleport methods intended usage along with updates to NetworkObject and physics areas of the documentation.

Pending Changelog Update

  • Changed: NetworkShow will now send a message at the end of the frame and will force a NetworkVariable synchronization prior to generating the CreateObjectMessage as opposed to waiting until the next network tick to synchronize the show with the update to NetworkVariables.

Documentation (WIP)

  • Includes documentation for existing public API entry points:
    • Updates to the SwitchTransformSpaceWhenParented XML API that provides additional information about usage.
    • Updates to the SetState and Teleport for more clarity on intended usage for both network topologies.
    • Updates to NetworkObject.SpawnWithOwnership to call out how spawning with ownership can impact things like NetworkTransform during the spawning sequence when using a client-server topology.
  • Includes updates to existing documentation:
    • Updates to NetworkTransform regarding the use of SwitchTransformSpaceWhenParented.
      • Add section covering spawning, order of operations, and how timing and network topology can impact the end result.
        • Include SetState/Teleport, spawning (with or without) ownership, and the authority motion model.
    • Updates to the NetworkObject spawning section
      • Expand the coverage to include:
        • Spawning then changing ownership vs SpawnWithOwnership
        • Spawning, NetworkTransform, and parenting.
    • Updated physics
      • Includes parenting physics objects using attachables.
    • Added a first pass (still could use some additions in the future) NetworkRigidbody section (pulled this part out of physics).

WIP Documentation

  • Add a "Netcode best practices" section (covers message delivery, order, states & events, timing, and cost).
  • Order of operations (under Netcode best practices)
    • Message delivery
      • Reliable Fragmented Sequenced
        • The sequenced portion assures messages are received in order
      • Add note about using a different network delivery can impact the order of operations.
        • Include some example scenarios of how changing the network delivery can impact the order of operations (include references to NeworkTransform, Rpcs, named, and unnamed messages).
    • Message queue order
      • What it is and when messages are queued vs deferred to be generated at the end of the frame.
    • Netcode script & message order
      • State updates and events
        • Everything boils down to messages
        • Local vs netcode states and events
      • Script order dictates message order
        • Messages are sent in the order they were created.
          • Messages are received in the order they were created on the sender's side.
      • Examples of how script can cause issues:
        • Add NetworkBehaviourReference and NetworkObjectReference example
          • Order of operations example that covers issues when sending a reference to a same frame locally spawned (with no observers) NetworkObject, changing ownership, showing, and then invoking an RPC (targeting client to show the object to) on an already spawned NetworkObject that uses a NetworkObjectReference and/or NetworkBehaviourReference as a parameter.
        • Add RPC order of operations documentation and the NetworkTransforms, parenting, ownership, and more.
        • Provide examples of issues with the solutions to resolving the issues.
    • Message cost
      • Observer vs no observer spawning and message cost.
      • Netcode design approach & message cost.
  • Look for areas in existing documentation that makes sense to link back to appropriate sections in the Order of operations section.
  • Update NetworkTransform unreliable delivery documentation and xml api to call out that it will impact the NetworkTransform's order of operations (when applied vs things like parenting, owenrship, etc).

Testing & QA (How your changes can be verified during release Playtest)

Functional Testing

Manual testing :

  • [ X ] Manual testing done
    • The original CharacterControllerMovingBodies project.
      • This verifies the existing functionality was not broken.
    • The manual test mentioned above that was used to replicate the user's issues and fix them.
      • This verifies (n) parenting events can occur on a single frame and it will be synchronized.

Automated tests:

  • Covered by existing automated tests
  • [ X ] Covered by new automated tests
    • (wip)

Does the change require QA team to:

  • Review automated tests?
  • Execute manual tests?
  • Provide feedback about the PR?

If any boxes above are checked the QA team will be automatically added as a PR reviewer.

Backports

This is an NGO v2.x.x specific issue. No backport is required.

Assure that the local InLocalSpace field is updated to match the parented status.
Reset IsTeleporting and ExplicitSet after invoking OnAuthorityPushTransformState so these values are preserved for user script.

Automatically adjust InLocalSpace when spawning a NeworkObject based on the NetworkObject's current parented status when SwitchTransformSpaceWhenParented is enabled.
Invoking the OnAuthorityPushTransformState and OnNetworkTransformStateUpdated when synchronizing in order to provide users with the NetworkTransformState used to synchronize a NetworkTransform when first spawned.
Revert moving where IsTeleportingNextFrame and ExplicitSet are reset.
Add WasTeleported to NetworkTransformState in order to preserve whether the pushed state was teleported or not.
Adding documentation updates.
XML API update
Copy link
Contributor

@jabbacakes jabbacakes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left suggestions on the smaller changes - have pushed a commit with changes to the larger new additions to the NetworkTransform page, mostly just trying to improve clarity and reduce verbiage.

This page is getting very long, might break it up at some point, but will do that in a separate PR.

NoelStephensUnity and others added 8 commits September 12, 2025 13:55
NetworkSpawnManager:
Relative to spawning only, process deferred messages after post spawn.

NetworkTransform:
Synchronize the SwitchTransformSpaceWhenParented flag when it changes on the authority side.
Perform an early check in CheckForStateChange for changes to SwitchTransformSpaceWhenParented.
Apply changes to SwitchTransformSpaceWhenParented when processing a state update on non-authority instance.
A complete refactoring of how parenting is handled when NetworkTransform.SwitchTransformSpaceWhenParented is enabled to provide a complete 1:1 match of (n) back-to-back parenting actions and/or many parenting actions that occur over several frames. This preserves the order of operations, sends 1 full state update plus an added parenting directive per action immediately, and then upon receiving the non-authority instances will apply the parenting, transform the local values and interpolators' queued entries  between transform spaces (world to local, local to world, or local to local).
@NoelStephensUnity
Copy link
Collaborator Author

/ci ngo

Standards/style fix.
@NoelStephensUnity
Copy link
Collaborator Author

/ci ngo

More hidden white spaces...
@NoelStephensUnity
Copy link
Collaborator Author

/ci ngo

Removing one line space
@NoelStephensUnity
Copy link
Collaborator Author

/ci ngo

@NoelStephensUnity NoelStephensUnity marked this pull request as ready for review September 15, 2025 13:31
@NoelStephensUnity NoelStephensUnity requested a review from a team as a code owner September 15, 2025 13:31
Regressed a previous fix when resolving the most current issue where generating a parent directive should only apply the parenting directive if it is the server and not the motion authority (whether local or world) and to assure if we are the motion authority we still set the m_PreviousParent in the event ownership changes and the NetworkTransform is using an owner authority motion model.
Minor adjustment after merge.
Don't invoke NetworkManager.OnDestroy unless the singleton is null and the current instance is not listening.
If we suddenly stopped and trying to update non-existent NetworkTransform instances, then just reset the NetworkTransformTickRegistration system.
Allow NetworkObjects to run through the despawn process if they are destroyed by something like the UnityEngine SceneManager when unloading a scene. Added validation check against the NetworkObject's GameObject's scene (IsValid) and whether the scene is loaded or not to determine if an error message should be logged or if it is just being destroyed due to the scene being unloaded (abrupt unloading like exiting play mode while in a session).
If a NetworkTransformMessage is received while in the middle of shutting down, then do not attempt to process it.
Changing #3687 adjustment to use the version of SpawnNetworkObjectLocally that accepts a SceneObject which doesn't invoke pre-spawn but does invoke post spawn and processes deferred messages.
These were moved in this PR to assure post spawn was invoked after the object was 100% done locally spawning and as a last step process any deferred messages targeting this object.
Made a few adjustments to this test in order to debug, added additional logging, and marked this test as needing to be updated (and extended).
removing whitespaces
Validating clients had initialized was some how was encapsulated within a verbose debug check. Not sure why this was passing before other than certain messages might have always been processed out of order before...?
Removing the previously removed post spawn invocation from the common spawn method (missed when merging).

Renaming the local spawn methods to reflect the context of the local spawn (i.e. authority is the first to spawn and then notify where non-authority is invoked by the authority's CreateObjectMessage). It will help keep the context clear (possible area to merge into one with a flag to determine if it is an authority or non-authority spawn action).
Minor adjustments to the test that caught this issue.
Added logs and condensed NetworkUpdate.
insert a whitespace
Removing whitespace at the end of the comment
Minor performance gain by using a pre-defined static network delivery that is registered by message type  within MessageDelivery.
Removing using directive.
Reverting changes to NetworkVariableCollectionsTests
Minor code clean up with a handful of additional comments.
Adjusting internal comments for clarity purposes.
This includes a different approach to handling  buffered linear interpolation conversion when switching transform space.
Making parent internal.
Removing additional script not used.
Noticed an issue with the world space approach and rotating platforms (parents).
This is a refactor of the same kind of approach (i.e. interpolator handles transform space updates) with the addition of tracking each measurement's parent, handling any transform space conversion if the current parent is different from the measurement's parent, and just keeping everything transform space relative.
Set the target parent when initializing.
Added additional checks when getting the current interpolated value to handle the interpolation frames between the current and next measurement states.
This resolves the issue where there was a de-synch between converting transform spaces.
Removing left over debug script.
This resolves the broken half float issue.
Fixing issue with synch when SwitchTransformSpaceWhenParented is disabled.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants