Fixed hierarchies migration. Fixed assert with invalid entity bounds

Signed-off-by: Sergey Pereslavtsev <pereslav@amazon.com>
This commit is contained in:
Sergey Pereslavtsev
2021-11-05 17:32:16 +00:00
parent 54c1b00902
commit 807d0d7a5a
2 changed files with 48 additions and 30 deletions
@@ -241,7 +241,13 @@ namespace Multiplayer
{ {
AZ::Entity* entity = it->second; AZ::Entity* entity = it->second;
NetBindComponent* netBindComponent = m_networkEntityTracker.GetNetBindComponent(entity); NetBindComponent* netBindComponent = m_networkEntityTracker.GetNetBindComponent(entity);
AZ::Aabb entityBounds = AZ::Interface<AzFramework::IEntityBoundsUnion>::Get()->GetEntityWorldBoundsUnion(entity->GetId()); AZ::Aabb entityBounds = AZ::Interface<AzFramework::IEntityBoundsUnion>::Get()->GetEntityWorldBoundsUnion(entity->GetId());
if (!entityBounds.IsValid())
{
continue;
}
entityBounds.Expand(AZ::Vector3(0.01f)); entityBounds.Expand(AZ::Vector3(0.01f));
if (netBindComponent->GetNetEntityRole() == NetEntityRole::Authority) if (netBindComponent->GetNetEntityRole() == NetEntityRole::Authority)
{ {
@@ -287,41 +293,15 @@ namespace Multiplayer
const IEntityDomain::EntitiesNotInDomain& entitiesNotInDomain = m_entityDomain->RetrieveEntitiesNotInDomain(); const IEntityDomain::EntitiesNotInDomain& entitiesNotInDomain = m_entityDomain->RetrieveEntitiesNotInDomain();
for (NetEntityId exitingId : entitiesNotInDomain) 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); NetworkEntityHandle entityHandle = m_networkEntityTracker.Get(entityId);
// We also need special handling for the NetworkHierarchy as well, since related entities need to be migrated together bool safeToExit = IsHierarchySafeToExit(entityHandle, entitiesNotInDomain);
NetworkHierarchyRootComponentController* hierarchyRootController = entityHandle.FindController<NetworkHierarchyRootComponentController>();
NetworkHierarchyChildComponentController* hierarchyChildController = entityHandle.FindController<NetworkHierarchyChildComponentController>();
// 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;
}
}
// Validate that we aren't already planning to remove this entity // Validate that we aren't already planning to remove this entity
if (safeToExit) if (safeToExit)
@@ -632,4 +612,40 @@ namespace Multiplayer
netEntity->GetName().c_str()); 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<NetworkHierarchyRootComponentController>();
NetworkHierarchyChildComponentController* hierarchyChildController = entityHandle.FindController<NetworkHierarchyChildComponentController>();
AZStd::vector<AZ::Entity*> 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;
}
} }
@@ -84,7 +84,9 @@ namespace Multiplayer
void DispatchLocalDeferredRpcMessages(); void DispatchLocalDeferredRpcMessages();
void UpdateEntityDomain(); void UpdateEntityDomain();
void OnEntityExitDomain(NetEntityId entityId); void OnEntityExitDomain(NetEntityId entityId, const IEntityDomain::EntitiesNotInDomain& entitiesNotInDomain);
bool IsHierarchySafeToExit(NetworkEntityHandle& entityHandle, const IEntityDomain::EntitiesNotInDomain& entitiesNotInDomain);
//! RootSpawnableNotificationBus //! RootSpawnableNotificationBus
//! @{ //! @{