Fix crash in character component when using prefabs (#798)
This commit is contained in:
+33
-10
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user