diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index c7582af83f..3240925f6e 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -241,7 +241,13 @@ namespace Multiplayer { AZ::Entity* entity = it->second; NetBindComponent* netBindComponent = m_networkEntityTracker.GetNetBindComponent(entity); + AZ::Aabb entityBounds = AZ::Interface::Get()->GetEntityWorldBoundsUnion(entity->GetId()); + if (!entityBounds.IsValid()) + { + continue; + } + entityBounds.Expand(AZ::Vector3(0.01f)); if (netBindComponent->GetNetEntityRole() == NetEntityRole::Authority) { @@ -287,41 +293,15 @@ namespace Multiplayer const IEntityDomain::EntitiesNotInDomain& entitiesNotInDomain = m_entityDomain->RetrieveEntitiesNotInDomain(); for (NetEntityId exitingId : entitiesNotInDomain) { - OnEntityExitDomain(exitingId); + OnEntityExitDomain(exitingId, entitiesNotInDomain); } } - void NetworkEntityManager::OnEntityExitDomain(NetEntityId entityId) + void NetworkEntityManager::OnEntityExitDomain(NetEntityId entityId, const IEntityDomain::EntitiesNotInDomain& entitiesNotInDomain) { - bool safeToExit = true; NetworkEntityHandle entityHandle = m_networkEntityTracker.Get(entityId); - // We also need special handling for the NetworkHierarchy as well, since related entities need to be migrated together - NetworkHierarchyRootComponentController* hierarchyRootController = entityHandle.FindController(); - NetworkHierarchyChildComponentController* hierarchyChildController = entityHandle.FindController(); - - // Find the root entity - AZ::Entity* hierarchyRootEntity = nullptr; - if (hierarchyRootController) - { - hierarchyRootEntity = hierarchyRootController->GetParent().GetHierarchicalRoot(); - } - else if (hierarchyChildController) - { - hierarchyRootEntity = hierarchyChildController->GetParent().GetHierarchicalRoot(); - } - - if (hierarchyRootEntity) - { - NetEntityId rootNetId = GetNetEntityIdById(hierarchyRootEntity->GetId()); - ConstNetworkEntityHandle rootEntityHandle = GetEntity(rootNetId); - - // Check if the root entity is still tracked by this authority - if (rootEntityHandle.Exists() && rootEntityHandle.GetNetBindComponent()->HasController()) - { - safeToExit = false; - } - } + bool safeToExit = IsHierarchySafeToExit(entityHandle, entitiesNotInDomain); // Validate that we aren't already planning to remove this entity if (safeToExit) @@ -632,4 +612,40 @@ namespace Multiplayer netEntity->GetName().c_str()); } } + + bool NetworkEntityManager::IsHierarchySafeToExit(NetworkEntityHandle& entityHandle, const IEntityDomain::EntitiesNotInDomain& entitiesNotInDomain) + { + bool safeToExit = true; + + // We also need special handling for the NetworkHierarchy as well, since related entities need to be migrated together + NetworkHierarchyRootComponentController* hierarchyRootController = entityHandle.FindController(); + NetworkHierarchyChildComponentController* hierarchyChildController = entityHandle.FindController(); + + AZStd::vector hierarchicalEntities; + + // Get the entities in this hierarchy + if (hierarchyRootController) + { + hierarchicalEntities = hierarchyRootController->GetParent().GetHierarchicalEntities(); + } + else if (hierarchyChildController) + { + hierarchicalEntities = hierarchyChildController->GetParent().GetHierarchicalEntities(); + } + + // Check if *all* entities in the hierarchy are ready to migrate. + // If any are still "in domain", keep the whole hierarchy within the current authority for now + for (AZ::Entity* entity : hierarchicalEntities) + { + NetEntityId netEntityId = GetNetEntityIdById(entity->GetId()); + if (netEntityId != InvalidNetEntityId && !entitiesNotInDomain.contains(netEntityId)) + { + safeToExit = false; + break; + } + } + + return safeToExit; + } + } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index 133c35dce0..56ea2bb72c 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -84,7 +84,9 @@ namespace Multiplayer void DispatchLocalDeferredRpcMessages(); void UpdateEntityDomain(); - void OnEntityExitDomain(NetEntityId entityId); + void OnEntityExitDomain(NetEntityId entityId, const IEntityDomain::EntitiesNotInDomain& entitiesNotInDomain); + + bool IsHierarchySafeToExit(NetworkEntityHandle& entityHandle, const IEntityDomain::EntitiesNotInDomain& entitiesNotInDomain); //! RootSpawnableNotificationBus //! @{