Skip to content

fix: In-scene NetworkObjects disabled but never re-enabled after scene transition #1354

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

NoelStephensUnity
Copy link
Collaborator

@NoelStephensUnity NoelStephensUnity commented Oct 25, 2021

Only when there is an in-scene placed NetworkObject that moves itself into the DDOL scene and there is a full scene transition (i.e. LoadSceneMode.Single) the in-scene placed NetworkObject will get disabled and never re-enabled.
This PR resolves the above issue.

MTT-1479

PR Checklist

  • Have you added a backport label (if needed)? For example, the type:backport-release-* label. After you backport the PR, the label changes to stat:backported-release-*.
  • Have you updated the changelog? Each package has a CHANGELOG.md file.

Changelog

com.unity.netcode.gameobjects

  • Fixed in-scene NetworkObjects that are moved into the DDOL scene not getting restored to their original active state (enabled/disabled) after a full scene transition (i.e. LoadSceneMode.Single).
  • Fixed all NetworkObjects marked to persist a full scene transition now are restored to their original active state (enabled/disabled) after a full scene transition (i.e. LoadSceneMode.Single).

Testing and Documentation

  • Includes unit tests.
  • No documentation changes or additions were necessary.

This is the fix for the in-scene NetworkObjects moved into DDOL and the after a scene transition they become disabled but never re-enabled.
Had to make some private methods internal for testing purposes.
Adding test to validate the fix.
white space fixes.
Adding comment above the primary line of code that is the fix for this PR
removing unused namespace.
@NoelStephensUnity NoelStephensUnity marked this pull request as ready for review October 25, 2021 22:18
private TestingState m_TestingState;

[UnityTest]
public IEnumerator DDOLMoveAndRestoreInSceneNetworkObject()
Copy link
Contributor

Choose a reason for hiding this comment

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

I can't tell what this test does by its name.
I also can't really tell what the test does by looking at the test method. Is it testing that MoveObjectsToDontDestroyOnLoad sets them to inactive? Is it testing that MoveObjectsFromDontDestroyOnLoadToScene sets them to active? Is it testing both?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah... I need to come up with a better name for that test probably.
The test uses those two methods when doing a full scene transition (i.e. LoadSceneMode.Single).

  • Pre-Scene Transition--> MoveObjectsToDontDestroyOnLoad (disables in-scene placed NOs in DDOL)
  • Load Scene
  • Post-Scene Transition--> MoveObjectsFromDontDestroyOnLoadToScene (enables in-scene placed NOs in DDOL)

I could just have easily manually disabled the NetworkObject and then just called the MoveObjectsFromDontDestroyOnLoadToScene method to validate the fix, but figured I might as well include the initial method that disables the in-scene placed NetworkObject (MoveObjectsToDontDestroyOnLoad) since that is what disables the NetworkObject(s) prior to doing the full scene transition.

@@ -1830,7 +1830,7 @@ internal void HandleSceneEvent(ulong clientId, FastBufferReader reader)
/// Moves all NetworkObjects that don't have the <see cref="NetworkObject.DestroyWithScene"/> set to
/// the "Do not destroy on load" scene.
/// </summary>
private void MoveObjectsToDontDestroyOnLoad()
internal void MoveObjectsToDontDestroyOnLoad()
Copy link
Contributor

Choose a reason for hiding this comment

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

It appears that these are being made internal so that you can test them directly? This is a testing anti-pattern. To paraphrase a great number of testing authorities: "How do you test internals? Through the public API."

Copy link
Collaborator Author

@NoelStephensUnity NoelStephensUnity Oct 26, 2021

Choose a reason for hiding this comment

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

Yeah... the test to validate this fix was a little tricky.
The only place the two methods pertaining to this bug and fix (MoveObjectsToDontDestroyOnLoad and MoveObjectsFromDontDestroyOnLoadToScene ) are called is when there is a full scene transition taking place. Since we cannot do a full scene transition (i.e. it would unload the Test Runner's temporary scene and would break the rest of the tests) in a unit and/or integration test, the only way to write a test (currently) to verify the fix in this PR was to create the same circumstances and call the same methods...which required them to be accessible.
If you want, I could reduce the anti-pattern footprint by just testing the MoveObjectsFromDontDestroyOnLoadToScene method and not including the MoveObjectsToDontDestroyOnLoad in that process (i.e. just disable it in the unit test itself).


public class ForcedInSceneBehaviour : NetworkBehaviour
{
public event Action OnNetworkObjectSpawned;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: this event system to generic condition tracker feels like overkill. Why not just have an InSceneNetworkObjectDDOLTest field on the network behaviour, assign it when you create it, and have it do something like InSceneNetworkObjectDDOLTest.OnEnabledWasCalled = true;

Then, in the test case, instead of the "waitforcondition" and "conditionmet(false)" stuff you can just do the waiting in-place and increase readability of the test:

            while (!OnEnabledWasCalled)
            {
                yield return new WaitForSeconds(m_ConditionMetFrequency);
            }

Copy link
Collaborator Author

@NoelStephensUnity NoelStephensUnity Oct 26, 2021

Choose a reason for hiding this comment

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

Sure, I could just do something like:

            while (networkObject.isActiveAndEnabled)
            {
                yield return new WaitForSeconds(m_ConditionMetFrequency);
            }

and to check it is re-enabled

            while (!networkObject.isActiveAndEnabled)
            {
                yield return new WaitForSeconds(m_ConditionMetFrequency);
            }

in place of the other stuff.

@@ -1916,6 +1916,8 @@ private void MoveObjectsFromDontDestroyOnLoadToScene(Scene scene)
{
if (sobj.gameObject.scene == DontDestroyOnLoadScene && (sobj.IsSceneObject == null || sobj.IsSceneObject.Value))
{
// set in-scene placed NetworkObjects back to active
sobj.gameObject.SetActive(true);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this going to enabled objects which the user disabled manually?

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe worth adding a few test cases:

  • Scene-placed objects not in DDOL shouldn't be impacted
  • Dynamic objects not in DDOL shouldn't be impacted
  • Scene-placed objects in DDOL which are active should stay active
  • Scene-Placed objects in DDOL which are inactive should stay inactive
  • Dynamic objects in DDOL which are active shouldn't be impacted

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I can do that.

Copy link
Collaborator Author

@NoelStephensUnity NoelStephensUnity Nov 1, 2021

Choose a reason for hiding this comment

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

The most recent updated test includes the following test cases where all NetworkObjects' DestroyWithScene are set to false:

  • Tests for both default enabled and disabled cases:
    • Scene-placed NetworkObjects not already in the DDOL
    • Dynamically spawned NetworkObjects not already in the DDOL
    • Scene-placed NetworkObjects already in the DDOL
    • Dynamically spawned NetworkObjects already in the DDOL

As a side note:
Both dynamically spawned and in-scene placed NetworkObjects that do not have the DestroyWithScene set to false will be despawned before the scene transition.

andrews-unity and others added 4 commits October 28, 2021 10:25
This now tracks the state of NetworkObjects when a full scene transition takes place.

This includes a refactored test for NetworkObjects (dynamically spawned and in-scene placed) that persist a full scene transition.
This makes sure that DestroyWithScene is set to false for all InSceneNetworkObjectState tests.
After peer review during PR Triage we all decided to not change or track a NetworkObject's parent GameObject's state and to not disable during full scene transition.

Removed all active state tracking dictionaries and references as well as removed disabling DDOL migrated GameObjects from the runtime NGO code base.

Adjusted the DDOL test to check the state is maintained throughout the scene transition.

The DDOL test only required a minor
Updating the changelog to reflect most recent updates.
Copy link
Contributor

@0xFA11 0xFA11 left a comment

Choose a reason for hiding this comment

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

🚀

@unity-cla-assistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@andrews-unity andrews-unity merged commit 19b34f1 into develop Nov 10, 2021
@andrews-unity andrews-unity deleted the fix/InScene-NetworkObjects-DDOL-Disabled-MTT-1479 branch November 10, 2021 07:06
andrews-unity pushed a commit that referenced this pull request Nov 24, 2021
…e transition (#1354)

* fix

This is the fix for the in-scene NetworkObjects moved into DDOL and the after a scene transition they become disabled but never re-enabled.

* test

Had to make some private methods internal for testing purposes.
Adding test to validate the fix.

* style

white space fixes.

* style

Adding comment above the primary line of code that is the fix for this PR

* style

removing unused namespace.

* style

removing several LFs

* fix and test

This now tracks the state of NetworkObjects when a full scene transition takes place.

This includes a refactored test for NetworkObjects (dynamically spawned and in-scene placed) that persist a full scene transition.

* test update

This makes sure that DestroyWithScene is set to false for all InSceneNetworkObjectState tests.

* style

Removing whitespace.

* updated changelog

Added entries for the fixes applied in this PR.

* refactor

After peer review during PR Triage we all decided to not change or track a NetworkObject's parent GameObject's state and to not disable during full scene transition.

Removed all active state tracking dictionaries and references as well as removed disabling DDOL migrated GameObjects from the runtime NGO code base.

Adjusted the DDOL test to check the state is maintained throughout the scene transition.

The DDOL test only required a minor

* updated changelog

Updating the changelog to reflect most recent updates.
andrews-unity added a commit that referenced this pull request Nov 24, 2021
…e transition (#1354) (#1465)

* fix

This is the fix for the in-scene NetworkObjects moved into DDOL and the after a scene transition they become disabled but never re-enabled.

* test

Had to make some private methods internal for testing purposes.
Adding test to validate the fix.

* style

white space fixes.

* style

Adding comment above the primary line of code that is the fix for this PR

* style

removing unused namespace.

* style

removing several LFs

* fix and test

This now tracks the state of NetworkObjects when a full scene transition takes place.

This includes a refactored test for NetworkObjects (dynamically spawned and in-scene placed) that persist a full scene transition.

* test update

This makes sure that DestroyWithScene is set to false for all InSceneNetworkObjectState tests.

* style

Removing whitespace.

* updated changelog

Added entries for the fixes applied in this PR.

* refactor

After peer review during PR Triage we all decided to not change or track a NetworkObject's parent GameObject's state and to not disable during full scene transition.

Removed all active state tracking dictionaries and references as well as removed disabling DDOL migrated GameObjects from the runtime NGO code base.

Adjusted the DDOL test to check the state is maintained throughout the scene transition.

The DDOL test only required a minor

* updated changelog

Updating the changelog to reflect most recent updates.

Co-authored-by: Noel Stephens <noel.stephens@unity3d.com>
mollstam pushed a commit to Keepsake-Games/com.unity.netcode.gameobjects that referenced this pull request Feb 13, 2023
…e transition (Unity-Technologies#1354)

* fix

This is the fix for the in-scene NetworkObjects moved into DDOL and the after a scene transition they become disabled but never re-enabled.

* test

Had to make some private methods internal for testing purposes.
Adding test to validate the fix.

* style

white space fixes.

* style

Adding comment above the primary line of code that is the fix for this PR

* style

removing unused namespace.

* style

removing several LFs

* fix and test

This now tracks the state of NetworkObjects when a full scene transition takes place.

This includes a refactored test for NetworkObjects (dynamically spawned and in-scene placed) that persist a full scene transition.

* test update

This makes sure that DestroyWithScene is set to false for all InSceneNetworkObjectState tests.

* style

Removing whitespace.

* updated changelog

Added entries for the fixes applied in this PR.

* refactor

After peer review during PR Triage we all decided to not change or track a NetworkObject's parent GameObject's state and to not disable during full scene transition.

Removed all active state tracking dictionaries and references as well as removed disabling DDOL migrated GameObjects from the runtime NGO code base.

Adjusted the DDOL test to check the state is maintained throughout the scene transition.

The DDOL test only required a minor

* updated changelog

Updating the changelog to reflect most recent updates.
mollstam pushed a commit to Keepsake-Games/com.unity.netcode.gameobjects that referenced this pull request Feb 13, 2023
…e transition (Unity-Technologies#1354) (Unity-Technologies#1465)

* fix

This is the fix for the in-scene NetworkObjects moved into DDOL and the after a scene transition they become disabled but never re-enabled.

* test

Had to make some private methods internal for testing purposes.
Adding test to validate the fix.

* style

white space fixes.

* style

Adding comment above the primary line of code that is the fix for this PR

* style

removing unused namespace.

* style

removing several LFs

* fix and test

This now tracks the state of NetworkObjects when a full scene transition takes place.

This includes a refactored test for NetworkObjects (dynamically spawned and in-scene placed) that persist a full scene transition.

* test update

This makes sure that DestroyWithScene is set to false for all InSceneNetworkObjectState tests.

* style

Removing whitespace.

* updated changelog

Added entries for the fixes applied in this PR.

* refactor

After peer review during PR Triage we all decided to not change or track a NetworkObject's parent GameObject's state and to not disable during full scene transition.

Removed all active state tracking dictionaries and references as well as removed disabling DDOL migrated GameObjects from the runtime NGO code base.

Adjusted the DDOL test to check the state is maintained throughout the scene transition.

The DDOL test only required a minor

* updated changelog

Updating the changelog to reflect most recent updates.

Co-authored-by: Noel Stephens <noel.stephens@unity3d.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants