Fix crash in character component when using prefabs (#798)

This commit is contained in:
amzn-sean
2021-05-19 14:18:54 +01:00
committed by GitHub
parent 85feef74dc
commit bf4b65afde
3 changed files with 41 additions and 10 deletions
@@ -73,7 +73,10 @@ namespace PhysX
{
}
CharacterControllerComponent::~CharacterControllerComponent() = default;
CharacterControllerComponent::~CharacterControllerComponent()
{
DisableController();
}
// AZ::Component
void CharacterControllerComponent::Init()
@@ -92,7 +95,7 @@ namespace PhysX
void CharacterControllerComponent::Deactivate()
{
DestroyController();
DisableController();
Physics::CollisionFilteringRequestBus::Handler::BusDisconnect();
AzPhysics::SimulatedBodyComponentRequestsBus::Handler::BusDisconnect();
@@ -198,7 +201,7 @@ namespace PhysX
void CharacterControllerComponent::DisablePhysics()
{
DestroyController();
DisableController();
}
bool CharacterControllerComponent::IsPhysicsEnabled() const
@@ -421,17 +424,32 @@ namespace PhysX
AZ::TransformBus::EventResult(entityTranslation, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation);
m_characterConfig->m_position = entityTranslation;
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
if (sceneInterface != nullptr)
{
AzPhysics::SimulatedBodyHandle bodyHandle = sceneInterface->AddSimulatedBody(defaultSceneHandle, m_characterConfig.get());
m_controller = azdynamic_cast<PhysX::CharacterController*>(sceneInterface->GetSimulatedBodyFromHandle(defaultSceneHandle, bodyHandle));
m_controllerBodyHandle = sceneInterface->AddSimulatedBody(defaultSceneHandle, m_characterConfig.get());
m_controller = azdynamic_cast<PhysX::CharacterController*>(
sceneInterface->GetSimulatedBodyFromHandle(defaultSceneHandle, m_controllerBodyHandle));
}
if (m_controller == nullptr)
{
AZ_Error("PhysX Character Controller Component", false, "Failed to create character controller.");
return;
}
if (sceneInterface != nullptr)
{
// if the scene removes this controller body, we should also clean up our resources.
m_onSimulatedBodyRemovedHandler = AzPhysics::SceneEvents::OnSimulationBodyRemoved::Handler(
[this]([[maybe_unused]] AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle) {
if (bodyHandle == m_controllerBodyHandle)
{
DestroyController();
}
});
sceneInterface->RegisterSimulationBodyRemovedHandler(defaultSceneHandle, m_onSimulatedBodyRemovedHandler);
}
CharacterControllerRequestBus::Handler::BusConnect(GetEntityId());
m_preSimulateHandler = AzPhysics::SystemEvents::OnPresimulateEvent::Handler(
@@ -447,7 +465,7 @@ namespace PhysX
}
}
void CharacterControllerComponent::DestroyController()
void CharacterControllerComponent::DisableController()
{
if (!IsPhysicsEnabled())
{
@@ -460,10 +478,15 @@ namespace PhysX
{
sceneInterface->RemoveSimulatedBody(m_controller->m_sceneOwner, m_controller->m_bodyHandle);
}
DestroyController();
}
void CharacterControllerComponent::DestroyController()
{
m_controller = nullptr;
m_preSimulateHandler.Disconnect();
m_onSimulatedBodyRemovedHandler.Disconnect();
CharacterControllerRequestBus::Handler::BusDisconnect();
}
} // namespace PhysX
@@ -131,7 +131,12 @@ namespace PhysX
void ToggleCollisionLayer(const AZStd::string& layerName, AZ::Crc32 colliderTag, bool enabled) override;
private:
// Creates the physics character controller in the current default physics scene.
// This will do nothing if the controller is already created.
void CreateController();
// Removes the physics character controller from the scene and will call DestroyController for clean up.
void DisableController();
// Cleans up all references and events used with the physics character controller.
void DestroyController();
void OnPreSimulate(float deltaTime);
@@ -139,6 +144,8 @@ namespace PhysX
AZStd::unique_ptr<Physics::CharacterConfiguration> m_characterConfig;
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfig;
PhysX::CharacterController* m_controller = nullptr;
AzPhysics::SimulatedBodyHandle m_controllerBodyHandle = AzPhysics::InvalidSimulatedBodyHandle;
AzPhysics::SystemEvents::OnPresimulateEvent::Handler m_preSimulateHandler;
AzPhysics::SceneEvents::OnSimulationBodyRemoved::Handler m_onSimulatedBodyRemovedHandler;
};
} // namespace PhysX
@@ -489,6 +489,7 @@ namespace PhysX
// Disable simulation on body (not signaling OnSimulationBodySimulationDisabled event)
DisableSimulationOfBodyInternal(*simulatedBody.second);
}
m_simulatedBodyRemovedEvent.Signal(m_sceneHandle, simulatedBody.second->m_bodyHandle);
delete simulatedBody.second;
}
}