From 7ac246bab50f388fe644c7af6e08915a710e836f Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Thu, 15 Apr 2021 12:00:09 +0100 Subject: [PATCH] Character controller now uses Add/Remove Simulated Body --- .../AzFramework/Physics/Character.h | 28 +++--- .../SimulatedBodyConfiguration.h | 2 +- .../AzFramework/Physics/SystemBus.h | 20 ---- .../API/CharacterController.cpp | 11 ++- .../PhysXCharacters/API/CharacterUtils.cpp | 91 +++++++++---------- .../PhysXCharacters/API/CharacterUtils.h | 8 +- .../CharacterControllerComponent.cpp | 67 ++++++-------- .../Components/CharacterControllerComponent.h | 8 +- Gems/PhysX/Code/Source/Scene/PhysXScene.cpp | 74 ++++++++++----- Gems/PhysX/Code/Source/Scene/PhysXScene.h | 2 - Gems/PhysX/Code/Source/SystemComponent.cpp | 9 -- Gems/PhysX/Code/Source/SystemComponent.h | 5 - .../Benchmarks/PhysXCharactersBenchmarks.cpp | 45 +++++---- 13 files changed, 184 insertions(+), 186 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Character.h b/Code/Framework/AzFramework/AzFramework/Physics/Character.h index c43c6de9e8..d6f67706f4 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Character.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Character.h @@ -28,7 +28,7 @@ namespace Physics class CharacterColliderNodeConfiguration { public: - AZ_RTTI(CharacterColliderNodeConfiguration, "{C16F3301-0979-400C-B734-692D83755C39}"); + AZ_RTTI(Physics::CharacterColliderNodeConfiguration, "{C16F3301-0979-400C-B734-692D83755C39}"); AZ_CLASS_ALLOCATOR_DECL virtual ~CharacterColliderNodeConfiguration() = default; @@ -42,7 +42,7 @@ namespace Physics class CharacterColliderConfiguration { public: - AZ_RTTI(CharacterColliderConfiguration, "{4DFF1434-DF5B-4ED5-BE0F-D3E66F9B331A}"); + AZ_RTTI(Physics::CharacterColliderConfiguration, "{4DFF1434-DF5B-4ED5-BE0F-D3E66F9B331A}"); AZ_CLASS_ALLOCATOR_DECL virtual ~CharacterColliderConfiguration() = default; @@ -63,21 +63,23 @@ namespace Physics { public: AZ_CLASS_ALLOCATOR(CharacterConfiguration, AZ::SystemAllocator, 0); - AZ_RTTI(CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration); + AZ_RTTI(Physics::CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration); virtual ~CharacterConfiguration() = default; static void Reflect(AZ::ReflectContext* context); - AzPhysics::CollisionGroups::Id m_collisionGroupId; ///< Which layers does this character collide with. - AzPhysics::CollisionLayer m_collisionLayer; ///< Which collision layer is this character on. - MaterialSelection m_materialSelection; ///< Material selected from library for the body associated with the character. - AZ::Vector3 m_upDirection = AZ::Vector3::CreateAxisZ(); ///< Up direction for character orientation and step behavior. - float m_maximumSlopeAngle = 30.0f; ///< The maximum slope on which the character can move, in degrees. - float m_stepHeight = 0.5f; ///< Affects what size steps the character can climb. - float m_minimumMovementDistance = 0.001f; ///< To avoid jittering, the controller will not attempt to move distances below this. - float m_maximumSpeed = 100.0f; ///< If the accumulated requested velocity for a tick exceeds this magnitude, it will be clamped. - AZStd::string m_colliderTag; ///< Used to identify the collider associated with the character controller. + AzPhysics::CollisionGroups::Id m_collisionGroupId; //!< Which layers does this character collide with. + AzPhysics::CollisionLayer m_collisionLayer; //!< Which collision layer is this character on. + MaterialSelection m_materialSelection; //!< Material selected from library for the body associated with the character. + AZ::Vector3 m_upDirection = AZ::Vector3::CreateAxisZ(); //!< Up direction for character orientation and step behavior. + float m_maximumSlopeAngle = 30.0f; //!< The maximum slope on which the character can move, in degrees. + float m_stepHeight = 0.5f; //!< Affects what size steps the character can climb. + float m_minimumMovementDistance = 0.001f; //!< To avoid jittering, the controller will not attempt to move distances below this. + float m_maximumSpeed = 100.0f; //!< If the accumulated requested velocity for a tick exceeds this magnitude, it will be clamped. + AZStd::string m_colliderTag; //!< Used to identify the collider associated with the character controller. + AZStd::shared_ptr m_shapeConfig = nullptr; //!< The shape to use when creating the character controller. + AZStd::vector> m_colliders; //!< The list of colliders to attach to the character controller. }; /// Basic implementation of common character-style needs as a WorldBody. Is not a full-functional ship-ready @@ -88,7 +90,7 @@ namespace Physics { public: AZ_CLASS_ALLOCATOR(Character, AZ::SystemAllocator, 0); - AZ_RTTI(Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody); + AZ_RTTI(Physics::Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody); ~Character() override = default; diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h index 47b05089de..203590adbb 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h @@ -29,7 +29,7 @@ namespace AzPhysics struct SimulatedBodyConfiguration { AZ_CLASS_ALLOCATOR_DECL; - AZ_RTTI(SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}"); + AZ_RTTI(AzPhysics::SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}"); static void Reflect(AZ::ReflectContext* context); SimulatedBodyConfiguration() = default; diff --git a/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h b/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h index 717f9e023c..f198551148 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h @@ -246,26 +246,6 @@ namespace Physics using SystemRequests = System; using SystemRequestBus = AZ::EBus; - /// Physics character system global requests. - class CharacterSystemRequests - : public AZ::EBusTraits - { - public: - // EBusTraits - // singleton pattern - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - - virtual ~CharacterSystemRequests() = default; - - /// Creates the physics representation used to handle basic character interactions (also known as a character - /// controller). - virtual AZStd::unique_ptr CreateCharacter(const CharacterConfiguration& characterConfig, - const ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) = 0; - }; - - typedef AZ::EBus CharacterSystemRequestBus; - /// Physics system global debug requests. class SystemDebugRequests : public AZ::EBusTraits diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterController.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterController.cpp index dba069ac29..9e5f92aa72 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterController.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterController.cpp @@ -311,7 +311,10 @@ namespace PhysX CreateShadowBody(configuration); SetTag(configuration.m_colliderTag); - m_simulating = true; + if (auto* sceneInterface = AZ::Interface::Get()) + { + sceneInterface->EnableSimulationOfBody(m_sceneOwner, m_bodyHandle); + } } void CharacterController::DisablePhysics() @@ -323,7 +326,11 @@ namespace PhysX DestroyShadowBody(); RemoveControllerFromScene(); - m_simulating = false; + + if (auto* sceneInterface = AZ::Interface::Get()) + { + sceneInterface->DisableSimulationOfBody(m_sceneOwner, m_bodyHandle); + } } void CharacterController::DestroyShadowBody() diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp index 2761980d1b..6523238430 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp @@ -96,25 +96,17 @@ namespace PhysX } } - AZStd::unique_ptr CreateCharacterController(const Physics::CharacterConfiguration& characterConfig, - const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle sceneHandle) + CharacterController* CreateCharacterController(PhysXScene* scene, + const Physics::CharacterConfiguration& characterConfig) { - physx::PxControllerManager* manager = nullptr; - AzPhysics::Scene* scene = nullptr; - PhysX::PhysXScene* physxScene = nullptr; - if (auto* physicsSystem = AZ::Interface::Get()) + if (scene == nullptr) { - scene = physicsSystem->GetScene(sceneHandle); - if (scene) - { - physxScene = azrtti_cast(scene); - if (physxScene) - { - manager = physxScene->GetOrCreateControllerManager(); - } - } + AZ_Error("PhysX Character Controller", false, "Failed to create character controller as the scene is null"); + return nullptr; } - if (!manager || !scene) + + physx::PxControllerManager* manager = scene->GetOrCreateControllerManager(); + if (manager == nullptr) { AZ_Error("PhysX Character Controller", false, "Could not retrieve character controller manager."); return nullptr; @@ -123,41 +115,47 @@ namespace PhysX auto callbackManager = AZStd::make_unique(); physx::PxController* pxController = nullptr; - auto* pxScene = static_cast(physxScene->GetNativePointer()); + auto* pxScene = static_cast(scene->GetNativePointer()); - if (shapeConfig.GetShapeType() == Physics::ShapeType::Capsule) + switch (characterConfig.m_shapeConfig->GetShapeType()) { - physx::PxCapsuleControllerDesc capsuleDesc; + case Physics::ShapeType::Capsule: + { + physx::PxCapsuleControllerDesc capsuleDesc; - const Physics::CapsuleShapeConfiguration& capsuleConfig = static_cast(shapeConfig); - // LY height means total height, PhysX means height of straight section - capsuleDesc.height = AZ::GetMax(epsilon, capsuleConfig.m_height - 2.0f * capsuleConfig.m_radius); - capsuleDesc.radius = capsuleConfig.m_radius; - capsuleDesc.climbingMode = physx::PxCapsuleClimbingMode::eCONSTRAINED; + const Physics::CapsuleShapeConfiguration& capsuleConfig = static_cast(*characterConfig.m_shapeConfig); + // LY height means total height, PhysX means height of straight section + capsuleDesc.height = AZ::GetMax(epsilon, capsuleConfig.m_height - 2.0f * capsuleConfig.m_radius); + capsuleDesc.radius = capsuleConfig.m_radius; + capsuleDesc.climbingMode = physx::PxCapsuleClimbingMode::eCONSTRAINED; - AppendShapeIndependentProperties(capsuleDesc, characterConfig, callbackManager.get()); - AppendPhysXSpecificProperties(capsuleDesc, characterConfig); - PHYSX_SCENE_WRITE_LOCK(pxScene); - pxController = manager->createController(capsuleDesc); // This internally adds the controller's actor to the scene - } - else if (shapeConfig.GetShapeType() == Physics::ShapeType::Box) - { - physx::PxBoxControllerDesc boxDesc; + AppendShapeIndependentProperties(capsuleDesc, characterConfig, callbackManager.get()); + AppendPhysXSpecificProperties(capsuleDesc, characterConfig); + PHYSX_SCENE_WRITE_LOCK(pxScene); + pxController = manager->createController(capsuleDesc); // This internally adds the controller's actor to the scene + } + break; + case Physics::ShapeType::Box: + { + physx::PxBoxControllerDesc boxDesc; - const Physics::BoxShapeConfiguration& boxConfig = static_cast(shapeConfig); - boxDesc.halfHeight = 0.5f * boxConfig.m_dimensions.GetZ(); - boxDesc.halfSideExtent = 0.5f * boxConfig.m_dimensions.GetY(); - boxDesc.halfForwardExtent = 0.5f * boxConfig.m_dimensions.GetX(); + const Physics::BoxShapeConfiguration& boxConfig = static_cast(*characterConfig.m_shapeConfig); + boxDesc.halfHeight = 0.5f * boxConfig.m_dimensions.GetZ(); + boxDesc.halfSideExtent = 0.5f * boxConfig.m_dimensions.GetY(); + boxDesc.halfForwardExtent = 0.5f * boxConfig.m_dimensions.GetX(); - AppendShapeIndependentProperties(boxDesc, characterConfig, callbackManager.get()); - AppendPhysXSpecificProperties(boxDesc, characterConfig); - PHYSX_SCENE_WRITE_LOCK(pxScene); - pxController = manager->createController(boxDesc); // This internally adds the controller's actor to the scene - } - else - { - AZ_Error("PhysX Character Controller", false, "PhysX only supports box and capsule shapes for character controllers."); - return nullptr; + AppendShapeIndependentProperties(boxDesc, characterConfig, callbackManager.get()); + AppendPhysXSpecificProperties(boxDesc, characterConfig); + PHYSX_SCENE_WRITE_LOCK(pxScene); + pxController = manager->createController(boxDesc); // This internally adds the controller's actor to the scene + } + break; + default: + { + AZ_Error("PhysX Character Controller", false, "PhysX only supports box and capsule shapes for character controllers."); + return nullptr; + } + break; } if (!pxController) @@ -166,8 +164,7 @@ namespace PhysX return nullptr; } - auto controller = AZStd::make_unique(pxController, AZStd::move(callbackManager), sceneHandle); - return controller; + return aznew CharacterController(pxController, AZStd::move(callbackManager), scene->GetSceneHandle()); } AZStd::unique_ptr CreateRagdoll(Physics::RagdollConfiguration& configuration, diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.h b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.h index 6eb10bd4eb..07aa4008d3 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.h +++ b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.h @@ -25,6 +25,7 @@ namespace Physics namespace PhysX { class CharacterController; + class PhysXScene; namespace Utils { @@ -33,10 +34,9 @@ namespace PhysX AZ::Outcome GetNodeIndex(const Physics::RagdollConfiguration& configuration, const AZStd::string& nodeName); //! Creates a character controller based on the supplied configuration in the specified world. - //! @param configuration Information required to create the controller such as shape, slope behavior etc. - //! @param sceneHandle A handle to the physics scene in which the character controller should be created. - AZStd::unique_ptr CreateCharacterController(const Physics::CharacterConfiguration& - characterConfig, const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle sceneHandle); + //! @param scene The scene to add the character controller to. + //! @param characterConfig Information required to create the controller such as shape, slope behavior etc. + CharacterController* CreateCharacterController(PhysXScene* scene, const Physics::CharacterConfiguration& characterConfig); //! Creates a ragdoll based on the specified setup and initial pose. //! @param configuration Information about collider geometry and joint setup required to initialize the ragdoll. diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.cpp index bd12b68ca3..26ef5f0032 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.cpp @@ -67,7 +67,7 @@ namespace PhysX CharacterControllerComponent::CharacterControllerComponent() = default; CharacterControllerComponent::CharacterControllerComponent(AZStd::unique_ptr characterConfig, - AZStd::unique_ptr shapeConfig) + AZStd::shared_ptr shapeConfig) : m_characterConfig(AZStd::move(characterConfig)) , m_shapeConfig(AZStd::move(shapeConfig)) { @@ -188,7 +188,7 @@ namespace PhysX Physics::Character* CharacterControllerComponent::GetCharacter() { - return m_controller.get(); + return m_controller; } void CharacterControllerComponent::EnablePhysics() @@ -217,7 +217,7 @@ namespace PhysX AzPhysics::SimulatedBody* CharacterControllerComponent::GetWorldBody() { - return m_controller.get(); + return GetCharacter(); } AzPhysics::SceneQueryHit CharacterControllerComponent::RayCast(const AzPhysics::RayCastRequest& request) @@ -382,7 +382,7 @@ namespace PhysX void CharacterControllerComponent::CreateController() { - if (m_controller) + if (IsPhysicsEnabled()) { return; } @@ -397,22 +397,33 @@ namespace PhysX m_characterConfig->m_debugName = GetEntity()->GetName(); m_characterConfig->m_entityId = GetEntityId(); + m_characterConfig->m_shapeConfig = m_shapeConfig; + // get all the collider shapes and add it to the config + PhysX::ColliderComponentRequestBus::EnumerateHandlersId(GetEntityId(), [this](PhysX::ColliderComponentRequests* handler) + { + auto shapes = handler->GetShapes(); + m_characterConfig->m_colliders.insert(m_characterConfig->m_colliders.end(), shapes.begin(), shapes.end()); + return true; + }); - m_controller = Utils::Characters::CreateCharacterController(*m_characterConfig, *m_shapeConfig, defaultSceneHandle); - if (!m_controller) + // It's usually more convenient to control the foot position rather than the centre of the capsule, so + // make the foot position coincide with the entity position. + AZ::Vector3 entityTranslation = AZ::Vector3::CreateZero(); + AZ::TransformBus::EventResult(entityTranslation, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation); + m_characterConfig->m_position = entityTranslation; + + AZ_Assert(m_controller == nullptr, "Calling create CharacterControllerComponent::CreateController() with an already created controller."); + if (auto* sceneInterface = AZ::Interface::Get()) + { + AzPhysics::SimulatedBodyHandle bodyHandle = sceneInterface->AddSimulatedBody(defaultSceneHandle, m_characterConfig.get()); + m_controller = azdynamic_cast(sceneInterface->GetSimulatedBodyFromHandle(defaultSceneHandle, bodyHandle)); + } + if (m_controller == nullptr) { AZ_Error("PhysX Character Controller Component", false, "Failed to create character controller."); return; } - m_controller->EnablePhysics(*m_characterConfig); - - AZ::Vector3 entityTranslation = AZ::Vector3::CreateZero(); - AZ::TransformBus::EventResult(entityTranslation, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation); - // It's usually more convenient to control the foot position rather than the centre of the capsule, so - // make the foot position coincide with the entity position. - m_controller->SetBasePosition(entityTranslation); - AttachColliders(*m_controller); - + CharacterControllerRequestBus::Handler::BusConnect(GetEntityId()); m_preSimulateHandler = AzPhysics::SystemEvents::OnPresimulateEvent::Handler( @@ -426,26 +437,21 @@ namespace PhysX { physXSystem->RegisterPreSimulateEvent(m_preSimulateHandler); } - - Physics::WorldBodyNotificationBus::Event(GetEntityId(), &Physics::WorldBodyNotifications::OnPhysicsEnabled); } void CharacterControllerComponent::DestroyController() { - if (!m_controller) + if (!IsPhysicsEnabled()) { return; } m_controller->DisablePhysics(); - // The character is first removed from the scene, and then its deletion is deferred. - // This ensures trigger exit events are raised correctly on deleted objects. + if (auto* sceneInterface = AZ::Interface::Get()) { - auto* scene = azdynamic_cast(m_controller->GetScene()); - AZ_Assert(scene, "Invalid PhysX scene"); - scene->DeferDelete(AZStd::move(m_controller)); - m_controller.reset(); + sceneInterface->RemoveSimulatedBody(m_controller->m_sceneOwner, m_controller->m_bodyHandle); + m_controller = nullptr; } m_preSimulateHandler.Disconnect(); @@ -454,17 +460,4 @@ namespace PhysX Physics::WorldBodyNotificationBus::Event(GetEntityId(), &Physics::WorldBodyNotifications::OnPhysicsDisabled); } - - void CharacterControllerComponent::AttachColliders(Physics::Character& character) - { - PhysX::ColliderComponentRequestBus::EnumerateHandlersId(GetEntityId(), [&character](PhysX::ColliderComponentRequests* handler) - { - for (auto& shape : handler->GetShapes()) - { - character.AttachShape(shape); - } - return true; - }); - } - } // namespace PhysX diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.h b/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.h index 42ac5d4cce..ca956b1757 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.h +++ b/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.h @@ -47,7 +47,7 @@ namespace PhysX CharacterControllerComponent(); CharacterControllerComponent(AZStd::unique_ptr characterConfig, - AZStd::unique_ptr shapeConfig); + AZStd::shared_ptr shapeConfig); ~CharacterControllerComponent(); static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) @@ -131,12 +131,12 @@ namespace PhysX private: void CreateController(); void DestroyController(); - void AttachColliders(Physics::Character& character); + void OnPreSimulate(float deltaTime); AZStd::unique_ptr m_characterConfig; - AZStd::unique_ptr m_shapeConfig; - AZStd::unique_ptr m_controller; + AZStd::shared_ptr m_shapeConfig; + PhysX::CharacterController* m_controller = nullptr; AzPhysics::SystemEvents::OnPresimulateEvent::Handler m_preSimulateHandler; }; } // namespace PhysX diff --git a/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp b/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp index 28c8cc327b..1e6eee774e 100644 --- a/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp +++ b/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,8 @@ #include #include #include +#include +#include #include namespace PhysX @@ -186,6 +189,26 @@ namespace PhysX return newBody; } + AzPhysics::SimulatedBody* CreateCharacterBody(PhysXScene* scene, + const Physics::CharacterConfiguration* characterConfig) + { + CharacterController* controller = Utils::Characters::CreateCharacterController(scene, *characterConfig); + if (controller == nullptr) + { + AZ_Error("PhysXScene", false, "Failed to create character controller."); + return nullptr; + } + controller->EnablePhysics(*characterConfig); + controller->SetBasePosition(characterConfig->m_position); + + for (auto shape : characterConfig->m_colliders) + { + controller->AttachShape(shape); + } + + return controller; + } + //helper to perform a ray cast AzPhysics::SceneQueryHits RayCast(const AzPhysics::RayCastRequest* raycastRequest, AZStd::vector& raycastBuffer, @@ -595,6 +618,10 @@ namespace PhysX newBody = Internal::CreateSimulatedBody( azdynamic_cast(simulatedBodyConfig), newBodyCrc); } + else if (azrtti_istypeof(simulatedBodyConfig)) + { + newBody = Internal::CreateCharacterBody(this, azdynamic_cast(simulatedBodyConfig)); + } if (newBody != nullptr) { @@ -850,20 +877,24 @@ namespace PhysX void PhysXScene::EnableSimulationOfBodyInternal(AzPhysics::SimulatedBody& body) { - auto pxActor = static_cast(body.GetNativePointer()); - AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor"); - + //character controller is a special actor and only needs the m_simulating flag set, + if (!azrtti_istypeof(body)) { - PHYSX_SCENE_WRITE_LOCK(m_pxScene); - m_pxScene->addActor(*pxActor); - } + auto pxActor = static_cast(body.GetNativePointer()); + AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor"); - if (azrtti_istypeof(body)) - { - auto rigidBody = azdynamic_cast(&body); - if (rigidBody->ShouldStartAsleep()) { - rigidBody->ForceAsleep(); + PHYSX_SCENE_WRITE_LOCK(m_pxScene); + m_pxScene->addActor(*pxActor); + } + + if (azrtti_istypeof(body)) + { + auto rigidBody = azdynamic_cast(&body); + if (rigidBody->ShouldStartAsleep()) + { + rigidBody->ForceAsleep(); + } } } @@ -872,14 +903,17 @@ namespace PhysX void PhysXScene::DisableSimulationOfBodyInternal(AzPhysics::SimulatedBody& body) { - auto pxActor = static_cast(body.GetNativePointer()); - AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor"); - + //character controller is a special actor and only needs the m_simulating flag set, + if (!azrtti_istypeof(body)) { - PHYSX_SCENE_WRITE_LOCK(m_pxScene); - m_pxScene->removeActor(*pxActor); - } + auto pxActor = static_cast(body.GetNativePointer()); + AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor"); + { + PHYSX_SCENE_WRITE_LOCK(m_pxScene); + m_pxScene->removeActor(*pxActor); + } + } body.m_simulating = false; } @@ -907,11 +941,6 @@ namespace PhysX return m_controllerManager; } - void PhysXScene::DeferDelete(AZStd::unique_ptr worldBody) - { - m_deferredDeletions_uniquePtrs.push_back(AZStd::move(worldBody)); - } - void* PhysXScene::GetNativePointer() const { return m_pxScene; @@ -924,7 +953,6 @@ namespace PhysX delete simulatedBody; } m_deferredDeletions.clear(); - m_deferredDeletions_uniquePtrs.clear(); } void PhysXScene::ProcessTriggerEvents() diff --git a/Gems/PhysX/Code/Source/Scene/PhysXScene.h b/Gems/PhysX/Code/Source/Scene/PhysXScene.h index ec708cee9e..8bf20fca55 100644 --- a/Gems/PhysX/Code/Source/Scene/PhysXScene.h +++ b/Gems/PhysX/Code/Source/Scene/PhysXScene.h @@ -73,7 +73,6 @@ namespace PhysX void* GetNativePointer() const override; physx::PxControllerManager* GetOrCreateControllerManager(); - void DeferDelete(AZStd::unique_ptr worldBody); private: void EnableSimulationOfBodyInternal(AzPhysics::SimulatedBody& body); @@ -93,7 +92,6 @@ namespace PhysX AZStd::vector> m_simulatedBodies; //this will become a SimulatedBody with LYN-1334 AZStd::vector m_deferredDeletions; - AZStd::vector> m_deferredDeletions_uniquePtrs; // this is to support Character as it stores itself in a unique pointer currently. AZStd::queue m_freeSceneSlots; AzPhysics::SystemEvents::OnConfigurationChangedEvent::Handler m_physicsSystemConfigChanged; diff --git a/Gems/PhysX/Code/Source/SystemComponent.cpp b/Gems/PhysX/Code/Source/SystemComponent.cpp index 8210492fe7..9ef4dc5099 100644 --- a/Gems/PhysX/Code/Source/SystemComponent.cpp +++ b/Gems/PhysX/Code/Source/SystemComponent.cpp @@ -211,7 +211,6 @@ namespace PhysX Physics::SystemRequestBus::Handler::BusConnect(); PhysX::SystemRequestsBus::Handler::BusConnect(); Physics::CollisionRequestBus::Handler::BusConnect(); - Physics::CharacterSystemRequestBus::Handler::BusConnect(); ActivatePhysXSystem(); } @@ -219,7 +218,6 @@ namespace PhysX void SystemComponent::Deactivate() { AZ::TickBus::Handler::BusDisconnect(); - Physics::CharacterSystemRequestBus::Handler::BusDisconnect(); Physics::CollisionRequestBus::Handler::BusDisconnect(); PhysX::SystemRequestsBus::Handler::BusDisconnect(); Physics::SystemRequestBus::Handler::BusDisconnect(); @@ -421,13 +419,6 @@ namespace PhysX } } - // Physics::CharacterSystemRequestBus - AZStd::unique_ptr SystemComponent::CreateCharacter(const Physics::CharacterConfiguration& - characterConfig, const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) - { - return Utils::Characters::CreateCharacterController(characterConfig, shapeConfig, sceneHandle); - } - AzPhysics::CollisionLayer SystemComponent::GetCollisionLayerByName(const AZStd::string& layerName) { return m_physXSystem->GetPhysXConfiguration().m_collisionConfig.m_collisionLayers.GetLayer(layerName); diff --git a/Gems/PhysX/Code/Source/SystemComponent.h b/Gems/PhysX/Code/Source/SystemComponent.h index 8c4ac0d836..8871adfeeb 100644 --- a/Gems/PhysX/Code/Source/SystemComponent.h +++ b/Gems/PhysX/Code/Source/SystemComponent.h @@ -57,7 +57,6 @@ namespace PhysX : public AZ::Component , public Physics::SystemRequestBus::Handler , public PhysX::SystemRequestsBus::Handler - , public Physics::CharacterSystemRequestBus::Handler , private Physics::CollisionRequestBus::Handler , private AZ::TickBus::Handler { @@ -96,10 +95,6 @@ namespace PhysX physx::PxFilterData CreateFilterData(const AzPhysics::CollisionLayer& layer, const AzPhysics::CollisionGroup& group) override; physx::PxCooking* GetCooking() override; - // Physics::CharacterSystemRequestBus - virtual AZStd::unique_ptr CreateCharacter(const Physics::CharacterConfiguration& characterConfig, - const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) override; - // CollisionRequestBus AzPhysics::CollisionLayer GetCollisionLayerByName(const AZStd::string& layerName) override; AZStd::string GetCollisionLayerName(const AzPhysics::CollisionLayer& layer) override; diff --git a/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersBenchmarks.cpp b/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersBenchmarks.cpp index 892d7b2da0..c7b9bd5623 100644 --- a/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersBenchmarks.cpp +++ b/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersBenchmarks.cpp @@ -130,7 +130,9 @@ namespace PhysX::Benchmarks //! @param colliderType, the collider type to use //! @param scene, the scene to spawn the characters controller into //! @param genSpawnPosFuncPtr - [optional] function pointer to allow caller to pick the spawn position - AZStd::vector> CreateCharacterControllers(int numCharacterControllers, CharacterConstants::CharacterSettings::ColliderType colliderType, + AZStd::vector CreateCharacterControllers( + int numCharacterControllers, + CharacterConstants::CharacterSettings::ColliderType colliderType, AzPhysics::SceneHandle& sceneHandle, GenerateSpawnPositionFuncPtr* genSpawnPosFuncPtr = nullptr) { @@ -139,12 +141,11 @@ namespace PhysX::Benchmarks characterConfig.m_maximumSlopeAngle = CharacterConstants::CharacterSettings::MaximumSlopeAngle; characterConfig.m_stepHeight = CharacterConstants::CharacterSettings::StepHeight; - Physics::ShapeConfiguration* shapeConfig = nullptr; switch (colliderType) { case CharacterConstants::CharacterSettings::ColliderType::Box: { - shapeConfig = new Physics::BoxShapeConfiguration( + characterConfig.m_shapeConfig = AZStd::make_shared( AZ::Vector3(CharacterConstants::CharacterSettings::CharacterBoxWidth, CharacterConstants::CharacterSettings::CharacterBoxDepth, CharacterConstants::CharacterSettings::CharacterBoxHeight) @@ -155,26 +156,32 @@ namespace PhysX::Benchmarks case CharacterConstants::CharacterSettings::ColliderType::Capsule: default: { - shapeConfig = new Physics::CapsuleShapeConfiguration(CharacterConstants::CharacterSettings::CharacterCylinderHeight, + characterConfig.m_shapeConfig = AZStd::make_shared( + CharacterConstants::CharacterSettings::CharacterCylinderHeight, CharacterConstants::CharacterSettings::CharacterCylinderRadius); } break; } - AZStd::vector> controllers; + auto* sceneInterface = AZ::Interface::Get(); + + AZStd::vector controllers; controllers.reserve(numCharacterControllers); for (int i = 0; i < numCharacterControllers; i++) { - AZStd::unique_ptr controller; - Physics::CharacterSystemRequestBus::BroadcastResult(controller, - &Physics::CharacterSystemRequests::CreateCharacter, characterConfig, *shapeConfig, sceneHandle); - - const AZ::Vector3 spawnPosition = genSpawnPosFuncPtr != nullptr ? (*genSpawnPosFuncPtr)(i) : AZ::Vector3::CreateZero(); - controller->SetBasePosition(spawnPosition); - - controllers.emplace_back(AZStd::move(controller)); + const AZ::Vector3 spawnPosition = genSpawnPosFuncPtr != nullptr ? (*genSpawnPosFuncPtr)(i) : AZ::Vector3::CreateZero(); + characterConfig.m_position = spawnPosition; + AzPhysics::SimulatedBodyHandle newHandle = sceneInterface->AddSimulatedBody(sceneHandle, &characterConfig); + if (newHandle != AzPhysics::InvalidSimulatedBodyHandle) + { + if (auto* characterPtr = azdynamic_cast( + sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, newHandle) + )) + { + controllers.emplace_back(characterPtr); + } + } } - delete shapeConfig; return controllers; } @@ -206,7 +213,7 @@ namespace PhysX::Benchmarks } return AZ::Vector3(x, y, z); }; - AZStd::vector> controllers = Utils::CreateCharacterControllers(numCharacters, + AZStd::vector controllers = Utils::CreateCharacterControllers(numCharacters, static_cast(state.range(1)), m_testSceneHandle, &posGenerator); //setup the sub tick tracker @@ -262,7 +269,7 @@ namespace PhysX::Benchmarks } return AZ::Vector3(x, y, z); }; - AZStd::vector> controllers = Utils::CreateCharacterControllers(numCharacters, + AZStd::vector controllers = Utils::CreateCharacterControllers(numCharacters, static_cast(state.range(1)), m_testSceneHandle, &posGenerator); //setup the sub tick tracker @@ -320,15 +327,15 @@ namespace PhysX::Benchmarks const float z = 0.0f; return AZ::Vector3(x, y, z); }; - AZStd::vector> controllers = Utils::CreateCharacterControllers(numCharacters, + AZStd::vector controllers = Utils::CreateCharacterControllers(numCharacters, static_cast(state.range(1)), m_testSceneHandle, &posGenerator); //pair up each character controller with a movement vector - using ControllerAndMovementDirPair = AZStd::pair, AZ::Vector3>; + using ControllerAndMovementDirPair = AZStd::pair; AZStd::vector targetMoveAndControllers; for (auto& controller : controllers) { - targetMoveAndControllers.emplace_back(ControllerAndMovementDirPair(AZStd::move(controller), AZ::Vector3::CreateZero())); + targetMoveAndControllers.emplace_back(ControllerAndMovementDirPair(controller, AZ::Vector3::CreateZero())); } //setup the sub tick tracker