@@ -185,15 +185,18 @@ private bool IsEditingPrefab()
185185 /// </remarks>
186186 private void CheckForInScenePlaced ( )
187187 {
188- if ( PrefabUtility . IsPartOfAnyPrefab ( this ) && ! IsEditingPrefab ( ) && gameObject . scene . IsValid ( ) && gameObject . scene . isLoaded && gameObject . scene . buildIndex >= 0 )
188+ if ( gameObject . scene . IsValid ( ) && gameObject . scene . isLoaded && gameObject . scene . buildIndex >= 0 )
189189 {
190- var prefab = PrefabUtility . GetCorrespondingObjectFromSource ( gameObject ) ;
191- var assetPath = AssetDatabase . GetAssetPath ( prefab ) ;
192- var sourceAsset = AssetDatabase . LoadAssetAtPath < NetworkObject > ( assetPath ) ;
193- if ( sourceAsset != null && sourceAsset . GlobalObjectIdHash != 0 && InScenePlacedSourceGlobalObjectIdHash != sourceAsset . GlobalObjectIdHash )
190+ if ( PrefabUtility . IsPartOfAnyPrefab ( this ) )
194191 {
195- InScenePlacedSourceGlobalObjectIdHash = sourceAsset . GlobalObjectIdHash ;
196- EditorUtility . SetDirty ( this ) ;
192+ var prefab = PrefabUtility . GetCorrespondingObjectFromSource ( gameObject ) ;
193+ var assetPath = AssetDatabase . GetAssetPath ( prefab ) ;
194+ var sourceAsset = AssetDatabase . LoadAssetAtPath < NetworkObject > ( assetPath ) ;
195+ if ( sourceAsset != null && sourceAsset . GlobalObjectIdHash != 0 && InScenePlacedSourceGlobalObjectIdHash != sourceAsset . GlobalObjectIdHash )
196+ {
197+ InScenePlacedSourceGlobalObjectIdHash = sourceAsset . GlobalObjectIdHash ;
198+ EditorUtility . SetDirty ( this ) ;
199+ }
197200 }
198201 IsSceneObject = true ;
199202 }
@@ -1241,7 +1244,7 @@ private void OnTransformParentChanged()
12411244 // we call CheckOrphanChildren() method and quickly iterate over OrphanChildren set and see if we can reparent/adopt one.
12421245 internal static HashSet < NetworkObject > OrphanChildren = new HashSet < NetworkObject > ( ) ;
12431246
1244- internal bool ApplyNetworkParenting ( bool removeParent = false , bool ignoreNotSpawned = false , bool orphanedChildPass = false )
1247+ internal bool ApplyNetworkParenting ( bool removeParent = false , bool ignoreNotSpawned = false , bool orphanedChildPass = false , bool enableNotification = true )
12451248 {
12461249 if ( ! AutoObjectParentSync )
12471250 {
@@ -1314,7 +1317,10 @@ internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpa
13141317 // to WorldPositionStays which can cause scaling issues if the parent's
13151318 // scale is not the default (Vetctor3.one) value.
13161319 transform . SetParent ( null , m_CachedWorldPositionStays ) ;
1317- InvokeBehaviourOnNetworkObjectParentChanged ( null ) ;
1320+ if ( enableNotification )
1321+ {
1322+ InvokeBehaviourOnNetworkObjectParentChanged ( null ) ;
1323+ }
13181324 return true ;
13191325 }
13201326
@@ -1340,7 +1346,10 @@ internal bool ApplyNetworkParenting(bool removeParent = false, bool ignoreNotSpa
13401346
13411347 m_CachedParent = parentObject . transform ;
13421348 transform . SetParent ( parentObject . transform , m_CachedWorldPositionStays ) ;
1343- InvokeBehaviourOnNetworkObjectParentChanged ( parentObject ) ;
1349+ if ( enableNotification )
1350+ {
1351+ InvokeBehaviourOnNetworkObjectParentChanged ( parentObject ) ;
1352+ }
13441353 return true ;
13451354 }
13461355
@@ -1819,6 +1828,8 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId)
18191828 {
18201829 var obj = new SceneObject
18211830 {
1831+ HasParent = transform . parent != null ,
1832+ WorldPositionStays = m_CachedWorldPositionStays ,
18221833 NetworkObjectId = NetworkObjectId ,
18231834 OwnerClientId = OwnerClientId ,
18241835 IsPlayerObject = IsPlayerObject ,
@@ -1829,31 +1840,16 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId)
18291840 TargetClientId = targetClientId
18301841 } ;
18311842
1832- NetworkObject parentNetworkObject = null ;
1833-
1834- if ( ! AlwaysReplicateAsRoot && transform . parent != null )
1843+ // Handle Parenting
1844+ if ( ! AlwaysReplicateAsRoot && obj . HasParent )
18351845 {
1836- parentNetworkObject = transform . parent . GetComponent < NetworkObject > ( ) ;
1837- // In-scene placed NetworkObjects parented under GameObjects with no NetworkObject
1838- // should set the has parent flag and preserve the world position stays value
1839- if ( parentNetworkObject == null && obj . IsSceneObject )
1840- {
1841- obj . HasParent = true ;
1842- obj . WorldPositionStays = m_CachedWorldPositionStays ;
1843- }
1844- }
1846+ var parentNetworkObject = transform . parent . GetComponent < NetworkObject > ( ) ;
18451847
1846- if ( parentNetworkObject != null )
1847- {
1848- obj . HasParent = true ;
1849- obj . ParentObjectId = parentNetworkObject . NetworkObjectId ;
1850- obj . WorldPositionStays = m_CachedWorldPositionStays ;
1851- var latestParent = GetNetworkParenting ( ) ;
1852- var isLatestParentSet = latestParent != null && latestParent . HasValue ;
1853- obj . IsLatestParentSet = isLatestParentSet ;
1854- if ( isLatestParentSet )
1848+ if ( parentNetworkObject )
18551849 {
1856- obj . LatestParent = latestParent . Value ;
1850+ obj . ParentObjectId = parentNetworkObject . NetworkObjectId ;
1851+ obj . LatestParent = GetNetworkParenting ( ) ;
1852+ obj . IsLatestParentSet = obj . LatestParent != null && obj . LatestParent . HasValue ;
18571853 }
18581854 }
18591855
@@ -1866,12 +1862,6 @@ internal SceneObject GetMessageSceneObject(ulong targetClientId)
18661862 var syncRotationPositionLocalSpaceRelative = obj . HasParent && ! m_CachedWorldPositionStays ;
18671863 var syncScaleLocalSpaceRelative = obj . HasParent && ! m_CachedWorldPositionStays ;
18681864
1869- // Always synchronize in-scene placed object's scale using local space
1870- if ( obj . IsSceneObject )
1871- {
1872- syncScaleLocalSpaceRelative = obj . HasParent ;
1873- }
1874-
18751865 // If auto object synchronization is turned off
18761866 if ( ! AutoObjectParentSync )
18771867 {
@@ -1949,6 +1939,15 @@ internal static NetworkObject AddSceneObject(in SceneObject sceneObject, FastBuf
19491939 var bufferSerializer = new BufferSerializer < BufferSerializerReader > ( new BufferSerializerReader ( reader ) ) ;
19501940 networkObject . SynchronizeNetworkBehaviours ( ref bufferSerializer , networkManager . LocalClientId ) ;
19511941
1942+ // If we are an in-scene placed NetworkObject and we originally had a parent but when synchronized we are
1943+ // being told we do not have a parent, then we want to clear the latest parent so it is not automatically
1944+ // "re-parented" to the original parent. This can happen if not unloading the scene and the parenting of
1945+ // the in-scene placed Networkobject changes several times over different sessions.
1946+ if ( sceneObject . IsSceneObject && ! sceneObject . HasParent && networkObject . m_LatestParent . HasValue )
1947+ {
1948+ networkObject . m_LatestParent = null ;
1949+ }
1950+
19521951 // Spawn the NetworkObject
19531952 networkManager . SpawnManager . SpawnNetworkObjectLocally ( networkObject , sceneObject , sceneObject . DestroyWithScene ) ;
19541953
0 commit comments