Skip to content

Commit 0e9d591

Browse files
Merge branch 'develop-2.0.0' into pvp-fixes-develop-2.0.0-round2
2 parents 8243284 + dfadc33 commit 0e9d591

File tree

13 files changed

+252
-180
lines changed

13 files changed

+252
-180
lines changed

.github/ISSUE_TEMPLATE/support.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ assignees: ''
77

88
---
99

10-
Post your questions or problems here.
10+
For support related questions we HIGHLY recommend to post a message either on the [Unity Discussions](https://discussions.unity.com/tag/netcode-for-gameobjects) or on our [Discord Community](https://discord.gg/TqNeJTtC) where you can get help from the community and the developers.
11+
Those forums will get you the fastest response and are the best place to ask for help.
1112

12-
For general questions, networking advice or discussions about the Netcode for GameObjects, you can also reach us on our [Discord Community](https://discord.gg/FM8SE9E) or create a post in the [Unity Multiplayer Forum](https://forum.unity.com/forums/multiplayer.26/).
13+
If you still feel like you want to open a support issue as an GitHub Issue, please make sure to include as much information as possible (also including any relevant code/project) to help us understand your problem.

.github/pull_request_template.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
<!-- Add short version of the JIRA ticket to the PR title (e.g. "feat: new shiny feature [MTT-123]") -->
44

5-
<!-- Add RFC link here if applicable. -->
6-
75
## Changelog
86

97
- Added: The package whose Changelog should be added to should be in the header. Delete the changelog section entirely if it's not needed.
@@ -26,3 +24,13 @@
2624
- [ ] Deprecation of the API is explained in the CHANGELOG.
2725
- [ ] The users can understand why this API was removed and what they should use instead.
2826
-->
27+
28+
## Backport
29+
30+
<!-- If this is a backport:
31+
- Add the following to the PR title: "\[Backport\] ..." .
32+
- Link to the original PR.
33+
If this needs a backport - state this here
34+
If a backport is not needed please provide the reason why.
35+
If the "Backports" section is not present it will lead to a CI test failure.
36+
-->
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# This workflow is designed to verify that the pull request description contains a "## Backport" section, which is important as a reminder to account for backports for anyone that works with NGO repository.
2+
# We have 2 development branches (develop and develop-2.0.0) and we need to ensure that relevant changes are landing in only one or both of them
3+
# If the "##Backport" section is missing, the workflow will fail and block the PR from merging, prompting the developer to add this section.
4+
5+
# The workflow is configured to run when PR is created as well as when it is edited which also counts simple description edits.
6+
7+
name: "NGO - Backport Verification"
8+
9+
on:
10+
pull_request:
11+
types: [opened, edited]
12+
branches:
13+
- develop
14+
- develop-2.0.0
15+
16+
jobs:
17+
backport-verification:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v3
22+
23+
- name: Check PR description
24+
uses: actions/github-script@v6
25+
with:
26+
script: |
27+
const pr = context.payload.pull_request;
28+
const body = pr.body || '';
29+
30+
if (!body.includes('## Backport')) {
31+
core.setFailed('PR description must include a "## Backport" section. Please add this section and provide information about this PR backport to develop or develop-2.0.0 branch respectively or explain why backport is not needed.');
32+
}

.yamato/webgl-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ webgl_build_{{ project.name }}_{{ platform.name }}_{{ editor }}:
4545
# Engine is initialized in ‘nographics’ mode since we don't need any graphics for this case (--extra-editor-arg=-nographics)
4646
# In case of failure the job will be rerunned once (--reruncount=1) with clean library (--clean-library-on-rerun)
4747
# This will perform only building phase (--build-only) with a timeout of 3m (--timeout=1800)
48-
- UnifiedTestRunner --suite=playmode --platform=WebGL --scripting-backend=il2cpp --testproject={{ project.path }} --editor-location=.Editor --artifacts_path=artifacts --player-save-path=build/players --extra-editor-arg=-batchmode --extra-editor-arg=-nographics --reruncount=1 --clean-library-on-rerun --build-only --timeout=1800
48+
- UnifiedTestRunner --suite=playmode --platform=WebGL --scripting-backend=il2cpp --testproject={{ project.path }} --editor-location=.Editor --artifacts_path=artifacts --player-save-path=build/players --extra-editor-arg=-batchmode --extra-editor-arg=-nographics --reruncount=1 --clean-library-on-rerun --build-only --timeout=2400
4949
artifacts:
5050
logs:
5151
paths:

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Additional documentation and release notes are available at [Multiplayer Documen
2222

2323
### Fixed
2424

25+
- Fixed issue where in-scene placed `NetworkObjects` could fail to synchronize its transform properly (especially without a `NetworkTransform`) if their parenting changes from the default when the scene is loaded and if the same scene remains loaded between network sessions while the parenting is completely different from the original hierarchy. (#3387)
26+
- Fixed an issue in `UnityTransport` where the transport would accept sends on invalid connections, leading to a useless memory allocation and confusing error message. (#3382)
2527
- Fixed issue where the time delta that interpolators used would not be properly updated during multiple fixed update invocations within the same player loop frame. (#3355)
2628
- Fixed issue when using a distributed authority network topology and many clients attempt to connect simultaneously the session owner could max-out the maximum in-flight reliable messages allowed, start dropping packets, and some of the connecting clients would fail to fully synchronize. (#3350)
2729
- Fixed issue when using a distributed authority network topology and scene management was disabled clients would not be able to spawn any new network prefab instances until synchronization was complete. (#3350)
@@ -43,6 +45,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
4345

4446
### Changed
4547

48+
- Changed the scene loading event serialization order for in-scene placed `NetworkObject`s to be based on their parent-child hierarchy. (#3387)
4649
- Changed the original `Lerp` interpolation type to `LegacyLerp`. (#3355)
4750
- Changed `BufferedLinearInterpolator<T>.Update(float deltaTime, NetworkTime serverTime)` as being deprecated since this method is only used for internal testing purposes. (#3337)
4851
- Changed error thrown when attempting to build a dedicated server with Unity Transport that uses websockets to provide more useful information to the user. (#3336)

com.unity.netcode.gameobjects/Runtime/Components/NetworkTransform.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2074,13 +2074,6 @@ private bool CheckForStateChange(ref NetworkTransformState networkState, ref Tra
20742074
// buffered values to the correct world or local space values.
20752075
forceState = SwitchTransformSpaceWhenParented;
20762076
}
2077-
#if COM_UNITY_MODULES_PHYSICS || COM_UNITY_MODULES_PHYSICS2D
2078-
else if (InLocalSpace && m_UseRigidbodyForMotion)
2079-
{
2080-
// TODO: Provide more options than just FixedJoint
2081-
Debug.LogError($"[Rigidbody] WHen using a Rigidbody for motion, you cannot use {nameof(InLocalSpace)}! If parenting, use the integrated FixedJoint or use a Joint on Authority side.");
2082-
}
2083-
#endif
20842077

20852078
// Check for parenting when synchronizing and/or teleporting
20862079
if (isSynchronization || networkState.IsTeleportingNextFrame)
@@ -3543,7 +3536,10 @@ private void InternalInitialization(bool isOwnershipChange = false)
35433536
{
35443537
if (CanCommitToTransform)
35453538
{
3546-
InLocalSpace = transform.parent != null;
3539+
if (NetworkObject.HasParentNetworkObject(transform))
3540+
{
3541+
InLocalSpace = true;
3542+
}
35473543
}
35483544
// Always apply this if SwitchTransformSpaceWhenParented is set.
35493545
TickSyncChildren = true;

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

Lines changed: 55 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -308,15 +308,18 @@ internal void OnValidate()
308308
/// </remarks>
309309
private void CheckForInScenePlaced()
310310
{
311-
if (PrefabUtility.IsPartOfAnyPrefab(this) && gameObject.scene.IsValid() && gameObject.scene.isLoaded && gameObject.scene.buildIndex >= 0)
311+
if (gameObject.scene.IsValid() && gameObject.scene.isLoaded && gameObject.scene.buildIndex >= 0)
312312
{
313-
var prefab = PrefabUtility.GetCorrespondingObjectFromSource(gameObject);
314-
var assetPath = AssetDatabase.GetAssetPath(prefab);
315-
var sourceAsset = AssetDatabase.LoadAssetAtPath<NetworkObject>(assetPath);
316-
if (sourceAsset != null && sourceAsset.GlobalObjectIdHash != 0 && InScenePlacedSourceGlobalObjectIdHash != sourceAsset.GlobalObjectIdHash)
313+
if (PrefabUtility.IsPartOfAnyPrefab(this))
317314
{
318-
InScenePlacedSourceGlobalObjectIdHash = sourceAsset.GlobalObjectIdHash;
319-
EditorUtility.SetDirty(this);
315+
var prefab = PrefabUtility.GetCorrespondingObjectFromSource(gameObject);
316+
var assetPath = AssetDatabase.GetAssetPath(prefab);
317+
var sourceAsset = AssetDatabase.LoadAssetAtPath<NetworkObject>(assetPath);
318+
if (sourceAsset != null && sourceAsset.GlobalObjectIdHash != 0 && InScenePlacedSourceGlobalObjectIdHash != sourceAsset.GlobalObjectIdHash)
319+
{
320+
InScenePlacedSourceGlobalObjectIdHash = sourceAsset.GlobalObjectIdHash;
321+
EditorUtility.SetDirty(this);
322+
}
320323
}
321324
IsSceneObject = true;
322325

@@ -335,6 +338,24 @@ private void CheckForInScenePlaced()
335338
}
336339
#endif // UNITY_EDITOR
337340

341+
internal bool HasParentNetworkObject(Transform transform)
342+
{
343+
if (transform.parent != null)
344+
{
345+
var networkObject = transform.parent.GetComponent<NetworkObject>();
346+
if (networkObject != null && networkObject != this)
347+
{
348+
return true;
349+
}
350+
351+
if (transform.parent.parent != null)
352+
{
353+
return HasParentNetworkObject(transform.parent);
354+
}
355+
}
356+
return false;
357+
}
358+
338359
/// <summary>
339360
/// Gets the NetworkManager that owns this NetworkObject instance
340361
/// </summary>
@@ -2372,7 +2393,7 @@ private void OnTransformParentChanged()
23722393
// we call CheckOrphanChildren() method and quickly iterate over OrphanChildren set and see if we can reparent/adopt one.
23732394
internal static HashSet<NetworkObject> OrphanChildren = new HashSet<NetworkObject>();
23742395

2375-
internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpawned = false, bool orphanedChildPass = false)
2396+
internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpawned = false, bool orphanedChildPass = false, bool enableNotification = true)
23762397
{
23772398
if (!AutoObjectParentSync)
23782399
{
@@ -2445,7 +2466,10 @@ internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpa
24452466
// to WorldPositionStays which can cause scaling issues if the parent's
24462467
// scale is not the default (Vetctor3.one) value.
24472468
transform.SetParent(null, m_CachedWorldPositionStays);
2448-
InvokeBehaviourOnNetworkObjectParentChanged(null);
2469+
if (enableNotification)
2470+
{
2471+
InvokeBehaviourOnNetworkObjectParentChanged(null);
2472+
}
24492473
return true;
24502474
}
24512475

@@ -2470,7 +2494,10 @@ internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpa
24702494
}
24712495
SetCachedParent(parentObject.transform);
24722496
transform.SetParent(parentObject.transform, m_CachedWorldPositionStays);
2473-
InvokeBehaviourOnNetworkObjectParentChanged(parentObject);
2497+
if (enableNotification)
2498+
{
2499+
InvokeBehaviourOnNetworkObjectParentChanged(parentObject);
2500+
}
24742501
return true;
24752502
}
24762503

@@ -3115,6 +3142,8 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId = NetworkManager
31153142
{
31163143
var obj = new SceneObject
31173144
{
3145+
HasParent = transform.parent != null,
3146+
WorldPositionStays = m_CachedWorldPositionStays,
31183147
NetworkObjectId = NetworkObjectId,
31193148
OwnerClientId = OwnerClientId,
31203149
IsPlayerObject = IsPlayerObject,
@@ -3131,31 +3160,16 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId = NetworkManager
31313160
TargetClientId = targetClientId
31323161
};
31333162

3134-
NetworkObject parentNetworkObject = null;
3135-
3136-
if (!AlwaysReplicateAsRoot && transform.parent != null)
3163+
// Handle Parenting
3164+
if (!AlwaysReplicateAsRoot && obj.HasParent)
31373165
{
3138-
parentNetworkObject = transform.parent.GetComponent<NetworkObject>();
3139-
// In-scene placed NetworkObjects parented under GameObjects with no NetworkObject
3140-
// should set the has parent flag and preserve the world position stays value
3141-
if (parentNetworkObject == null && obj.IsSceneObject)
3142-
{
3143-
obj.HasParent = true;
3144-
obj.WorldPositionStays = m_CachedWorldPositionStays;
3145-
}
3146-
}
3166+
var parentNetworkObject = transform.parent.GetComponent<NetworkObject>();
31473167

3148-
if (parentNetworkObject != null)
3149-
{
3150-
obj.HasParent = true;
3151-
obj.ParentObjectId = parentNetworkObject.NetworkObjectId;
3152-
obj.WorldPositionStays = m_CachedWorldPositionStays;
3153-
var latestParent = GetNetworkParenting();
3154-
var isLatestParentSet = latestParent != null && latestParent.HasValue;
3155-
obj.IsLatestParentSet = isLatestParentSet;
3156-
if (isLatestParentSet)
3168+
if (parentNetworkObject)
31573169
{
3158-
obj.LatestParent = latestParent.Value;
3170+
obj.ParentObjectId = parentNetworkObject.NetworkObjectId;
3171+
obj.LatestParent = GetNetworkParenting();
3172+
obj.IsLatestParentSet = obj.LatestParent != null && obj.LatestParent.HasValue;
31593173
}
31603174
}
31613175

@@ -3168,12 +3182,6 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId = NetworkManager
31683182
var syncRotationPositionLocalSpaceRelative = obj.HasParent && !m_CachedWorldPositionStays;
31693183
var syncScaleLocalSpaceRelative = obj.HasParent && !m_CachedWorldPositionStays;
31703184

3171-
// Always synchronize in-scene placed object's scale using local space
3172-
if (obj.IsSceneObject)
3173-
{
3174-
syncScaleLocalSpaceRelative = obj.HasParent;
3175-
}
3176-
31773185
// If auto object synchronization is turned off
31783186
if (!AutoObjectParentSync)
31793187
{
@@ -3251,6 +3259,15 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
32513259
var bufferSerializer = new BufferSerializer<BufferSerializerReader>(new BufferSerializerReader(reader));
32523260
networkObject.SynchronizeNetworkBehaviours(ref bufferSerializer, networkManager.LocalClientId);
32533261

3262+
// If we are an in-scene placed NetworkObject and we originally had a parent but when synchronized we are
3263+
// being told we do not have a parent, then we want to clear the latest parent so it is not automatically
3264+
// "re-parented" to the original parent. This can happen if not unloading the scene and the parenting of
3265+
// the in-scene placed Networkobject changes several times over different sessions.
3266+
if (sceneObject.IsSceneObject && !sceneObject.HasParent && networkObject.m_LatestParent.HasValue)
3267+
{
3268+
networkObject.m_LatestParent = null;
3269+
}
3270+
32543271
// Spawn the NetworkObject
32553272
networkManager.SpawnManager.SpawnNetworkObjectLocally(networkObject, sceneObject, sceneObject.DestroyWithScene);
32563273

com.unity.netcode.gameobjects/Runtime/SceneManagement/SceneEventData.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,14 @@ internal void AddSpawnedNetworkObjects()
329329
m_NetworkObjectsSync.Add(sobj);
330330
}
331331
}
332+
SortObjectsToSync();
333+
}
332334

335+
/// <summary>
336+
/// Used to order the object serialization for both synchronization and scene loading
337+
/// </summary>
338+
private void SortObjectsToSync()
339+
{
333340
// Sort by INetworkPrefabInstanceHandler implementation before the
334341
// NetworkObjects spawned by the implementation
335342
m_NetworkObjectsSync.Sort(SortNetworkObjects);
@@ -671,20 +678,31 @@ internal void SerializeScenePlacedObjects(FastBufferWriter writer)
671678
// If distributed authority mode and sending to the service, then ignore observers
672679
var distributedAuthoritySendingToService = distributedAuthority && TargetClientId == NetworkManager.ServerClientId;
673680

681+
// Clear our objects to sync and build a list of the in-scene placed NetworkObjects instantiated and spawned locally
682+
m_NetworkObjectsSync.Clear();
674683
foreach (var keyValuePairByGlobalObjectIdHash in m_NetworkManager.SceneManager.ScenePlacedObjects)
675684
{
676685
foreach (var keyValuePairBySceneHandle in keyValuePairByGlobalObjectIdHash.Value)
677686
{
678687
if (keyValuePairBySceneHandle.Value.Observers.Contains(TargetClientId) || distributedAuthoritySendingToService)
679688
{
680-
// Serialize the NetworkObject
681-
var sceneObject = keyValuePairBySceneHandle.Value.GetMessageSceneObject(TargetClientId, distributedAuthority);
682-
sceneObject.Serialize(writer);
683-
numberOfObjects++;
689+
m_NetworkObjectsSync.Add(keyValuePairBySceneHandle.Value);
684690
}
685691
}
686692
}
687693

694+
// Sort the objects to sync based on parenting hierarchy
695+
SortObjectsToSync();
696+
697+
// Serialize the sorted objects to sync.
698+
foreach (var objectToSycn in m_NetworkObjectsSync)
699+
{
700+
// Serialize the NetworkObject
701+
var sceneObject = objectToSycn.GetMessageSceneObject(TargetClientId, distributedAuthority);
702+
sceneObject.Serialize(writer);
703+
numberOfObjects++;
704+
}
705+
688706
// Write the number of despawned in-scene placed NetworkObjects
689707
writer.WriteValueSafe(m_DespawnedInSceneObjectsSync.Count);
690708
// Write the scene handle and GlobalObjectIdHash value

0 commit comments

Comments
 (0)