1f9b284de2
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> # Conflicts: # Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h # Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h # Code/Editor/Plugins/EditorCommon/stdafx.cpp # Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h # Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h # Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h # Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h # Code/Tools/AssetProcessor/native/precompiled.h # Code/Tools/Standalone/StandaloneTools_precompiled.h # Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h # Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h # Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h # Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h # Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake # Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h # Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h # Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp # Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake # Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h # Gems/Blast/Code/Source/StdAfx.cpp # Gems/Camera/Code/Source/Camera_precompiled.h # Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h # Gems/FastNoise/Code/Source/FastNoise_precompiled.h # Gems/Gestures/Code/Source/Gestures_precompiled.h # Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h # Gems/GraphCanvas/Code/precompiled.h # Gems/ImGui/Code/Source/ImGui_precompiled.h # Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h # Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h # Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp # Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h # Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h # Gems/LyShine/Code/Source/LyShine_precompiled.h # Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h # Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h # Gems/Maestro/Code/Source/Maestro_precompiled.h # Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h # Gems/Metastream/Code/Source/Metastream_precompiled.h # Gems/Microphone/Code/Source/Microphone_precompiled.h # Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h # Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h # Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h # Gems/PhysX/Code/Source/PhysX_precompiled.h # Gems/PhysX/Code/physx_unsupported_files.cmake # Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h # Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h # Gems/ScriptCanvas/Code/Editor/precompiled.h # Gems/ScriptCanvas/Code/Source/precompiled.h # Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h # Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h # Gems/ScriptEvents/Code/Source/precompiled.h # Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp # Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h # Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h # Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h # Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h # Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h # Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h # Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h # Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h # Gems/Twitch/Code/Source/Twitch_precompiled.h # Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
562 lines
19 KiB
C++
562 lines
19 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <AzCore/Component/Entity.h>
|
|
#include <AzCore/Component/TransformBus.h>
|
|
#include <AzCore/RTTI/BehaviorContext.h>
|
|
#include <AzCore/Serialization/EditContext.h>
|
|
#include <AzCore/std/smart_ptr/make_shared.h>
|
|
#include <PhysXCharacters/API/CharacterController.h>
|
|
#include <PhysXCharacters/Components/CharacterControllerComponent.h>
|
|
#include <PhysX/ColliderComponentBus.h>
|
|
#include <Scene/PhysXScene.h>
|
|
#include <System/PhysXSystem.h>
|
|
#include <AzFramework/Physics/Utils.h>
|
|
#include <PhysXCharacters/API/CharacterUtils.h>
|
|
|
|
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
|
|
#include <AzFramework/Physics/Collision/CollisionGroups.h>
|
|
#include <AzFramework/Physics/Collision/CollisionLayers.h>
|
|
|
|
namespace PhysX
|
|
{
|
|
void CharacterControllerComponent::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
CharacterControllerConfiguration::Reflect(context);
|
|
CharacterController::Reflect(context);
|
|
|
|
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
|
{
|
|
serializeContext->Class<CharacterControllerComponent, AZ::Component>()
|
|
->Version(1)
|
|
->Field("CharacterConfig", &CharacterControllerComponent::m_characterConfig)
|
|
->Field("ShapeConfig", &CharacterControllerComponent::m_shapeConfig)
|
|
;
|
|
}
|
|
|
|
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
|
{
|
|
behaviorContext->EBus<CharacterControllerRequestBus>("PhysXCharacterControllerRequestBus",
|
|
"Character Controller (PhysX specific)")
|
|
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::RuntimeOwn)
|
|
->Attribute(AZ::Edit::Attributes::Category, "PhysX")
|
|
->Event("Resize", &CharacterControllerRequests::Resize)
|
|
->Event("GetHeight", &CharacterControllerRequests::GetHeight, "Get Height")
|
|
->Event("SetHeight", &CharacterControllerRequests::SetHeight, "Set Height")
|
|
->Event("GetRadius", &CharacterControllerRequests::GetRadius, "Get Radius")
|
|
->Event("SetRadius", &CharacterControllerRequests::SetRadius, "Set Radius")
|
|
->Event("GetHalfSideExtent", &CharacterControllerRequests::GetHalfSideExtent, "Get Half Side Extent")
|
|
->Event("SetHalfSideExtent", &CharacterControllerRequests::SetHalfSideExtent, "Set Half Side Extent")
|
|
->Event("GetHalfForwardExtent", &CharacterControllerRequests::GetHalfForwardExtent, "Get Half Forward Extent")
|
|
->Event("SetHalfForwardExtent", &CharacterControllerRequests::SetHalfForwardExtent, "Set Half Forward Extent")
|
|
;
|
|
}
|
|
}
|
|
|
|
CharacterControllerComponent::CharacterControllerComponent() = default;
|
|
|
|
CharacterControllerComponent::CharacterControllerComponent(AZStd::unique_ptr<Physics::CharacterConfiguration> characterConfig,
|
|
AZStd::shared_ptr<Physics::ShapeConfiguration> shapeConfig)
|
|
: m_characterConfig(AZStd::move(characterConfig))
|
|
, m_shapeConfig(AZStd::move(shapeConfig))
|
|
{
|
|
}
|
|
|
|
CharacterControllerComponent::~CharacterControllerComponent()
|
|
{
|
|
DisableController();
|
|
}
|
|
|
|
// AZ::Component
|
|
void CharacterControllerComponent::Init()
|
|
{
|
|
}
|
|
|
|
void CharacterControllerComponent::Activate()
|
|
{
|
|
CreateController();
|
|
|
|
AZ::TransformNotificationBus::Handler::BusConnect(GetEntityId());
|
|
Physics::CharacterRequestBus::Handler::BusConnect(GetEntityId());
|
|
Physics::CollisionFilteringRequestBus::Handler::BusConnect(GetEntityId());
|
|
AzPhysics::SimulatedBodyComponentRequestsBus::Handler::BusConnect(GetEntityId());
|
|
}
|
|
|
|
void CharacterControllerComponent::Deactivate()
|
|
{
|
|
DisableController();
|
|
|
|
Physics::CollisionFilteringRequestBus::Handler::BusDisconnect();
|
|
AzPhysics::SimulatedBodyComponentRequestsBus::Handler::BusDisconnect();
|
|
AZ::TransformNotificationBus::Handler::BusDisconnect();
|
|
Physics::CharacterRequestBus::Handler::BusDisconnect();
|
|
}
|
|
|
|
AZ::Vector3 CharacterControllerComponent::GetBasePosition() const
|
|
{
|
|
if (auto* controller = GetControllerConst())
|
|
{
|
|
return controller->GetBasePosition();
|
|
}
|
|
return AZ::Vector3::CreateZero();
|
|
}
|
|
|
|
void CharacterControllerComponent::SetBasePosition(const AZ::Vector3& position)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->SetBasePosition(position);
|
|
AZ::TransformBus::Event(GetEntityId(), &AZ::TransformBus::Events::SetWorldTranslation, position);
|
|
}
|
|
}
|
|
|
|
AZ::Vector3 CharacterControllerComponent::GetCenterPosition() const
|
|
{
|
|
if (auto* controller = GetControllerConst())
|
|
{
|
|
return controller->GetCenterPosition();
|
|
}
|
|
return AZ::Vector3::CreateZero();
|
|
}
|
|
|
|
float CharacterControllerComponent::GetStepHeight() const
|
|
{
|
|
if (auto* controller = GetControllerConst())
|
|
{
|
|
return controller->GetStepHeight();
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
void CharacterControllerComponent::SetStepHeight(float stepHeight)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->SetStepHeight(stepHeight);
|
|
}
|
|
}
|
|
|
|
AZ::Vector3 CharacterControllerComponent::GetUpDirection() const
|
|
{
|
|
if (auto* controller = GetControllerConst())
|
|
{
|
|
return controller->GetUpDirection();
|
|
}
|
|
return AZ::Vector3::CreateZero();
|
|
}
|
|
|
|
void CharacterControllerComponent::SetUpDirection([[maybe_unused]] const AZ::Vector3& upDirection)
|
|
{
|
|
AZ_Warning("PhysX Character Controller Component", false, "Setting up direction is not currently supported.");
|
|
}
|
|
|
|
float CharacterControllerComponent::GetSlopeLimitDegrees() const
|
|
{
|
|
if (auto* controller = GetControllerConst())
|
|
{
|
|
return controller->GetSlopeLimitDegrees();
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
void CharacterControllerComponent::SetSlopeLimitDegrees(float slopeLimitDegrees)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->SetSlopeLimitDegrees(slopeLimitDegrees);
|
|
}
|
|
}
|
|
|
|
float CharacterControllerComponent::GetMaximumSpeed() const
|
|
{
|
|
if (auto* controller = GetControllerConst())
|
|
{
|
|
return controller->GetMaximumSpeed();
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
void CharacterControllerComponent::SetMaximumSpeed(float maximumSpeed)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->SetMaximumSpeed(maximumSpeed);
|
|
}
|
|
}
|
|
|
|
AZ::Vector3 CharacterControllerComponent::GetVelocity() const
|
|
{
|
|
if (auto* controller = GetControllerConst())
|
|
{
|
|
return controller->GetVelocity();
|
|
}
|
|
return AZ::Vector3::CreateZero();
|
|
}
|
|
|
|
void CharacterControllerComponent::AddVelocity(const AZ::Vector3& velocity)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->AddVelocity(velocity);
|
|
}
|
|
}
|
|
|
|
Physics::Character* CharacterControllerComponent::GetCharacter()
|
|
{
|
|
return GetController();
|
|
}
|
|
|
|
void CharacterControllerComponent::EnablePhysics()
|
|
{
|
|
CreateController();
|
|
}
|
|
|
|
void CharacterControllerComponent::DisablePhysics()
|
|
{
|
|
DisableController();
|
|
}
|
|
|
|
bool CharacterControllerComponent::IsPhysicsEnabled() const
|
|
{
|
|
return GetControllerConst() != nullptr;
|
|
}
|
|
|
|
AZ::Aabb CharacterControllerComponent::GetAabb() const
|
|
{
|
|
if (auto* controller = GetControllerConst())
|
|
{
|
|
return controller->GetAabb();
|
|
}
|
|
return AZ::Aabb::CreateNull();
|
|
}
|
|
|
|
AzPhysics::SimulatedBody* CharacterControllerComponent::GetSimulatedBody()
|
|
{
|
|
return GetCharacter();
|
|
}
|
|
|
|
AzPhysics::SimulatedBodyHandle CharacterControllerComponent::GetSimulatedBodyHandle() const
|
|
{
|
|
return m_controllerBodyHandle;
|
|
}
|
|
|
|
AzPhysics::SceneQueryHit CharacterControllerComponent::RayCast(const AzPhysics::RayCastRequest& request)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
return controller->RayCast(request);
|
|
}
|
|
|
|
return AzPhysics::SceneQueryHit();
|
|
}
|
|
|
|
// CharacterControllerRequestBus
|
|
void CharacterControllerComponent::Resize(float height)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->Resize(height);
|
|
}
|
|
}
|
|
|
|
float CharacterControllerComponent::GetHeight()
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
return controller->GetHeight();
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
void CharacterControllerComponent::SetHeight(float height)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->SetHeight(height);
|
|
}
|
|
}
|
|
|
|
float CharacterControllerComponent::GetRadius()
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
return controller->GetRadius();
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
void CharacterControllerComponent::SetRadius(float radius)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->SetRadius(radius);
|
|
}
|
|
}
|
|
|
|
float CharacterControllerComponent::GetHalfSideExtent()
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
return controller->GetHalfSideExtent();
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
void CharacterControllerComponent::SetHalfSideExtent(float halfSideExtent)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->SetHalfSideExtent(halfSideExtent);
|
|
}
|
|
}
|
|
|
|
float CharacterControllerComponent::GetHalfForwardExtent()
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
return controller->GetHalfForwardExtent();
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
void CharacterControllerComponent::SetHalfForwardExtent(float halfForwardExtent)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->SetHalfForwardExtent(halfForwardExtent);
|
|
}
|
|
}
|
|
|
|
// TransformNotificationBus
|
|
void CharacterControllerComponent::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->SetBasePosition(world.GetTranslation());
|
|
}
|
|
}
|
|
|
|
void CharacterControllerComponent::SetCollisionLayer(const AZStd::string& layerName, AZ::Crc32 colliderTag)
|
|
{
|
|
auto* controller = GetController();
|
|
if (controller == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (Physics::Utils::FilterTag(controller->GetColliderTag(), colliderTag))
|
|
{
|
|
bool success = false;
|
|
AzPhysics::CollisionLayer collisionLayer;
|
|
Physics::CollisionRequestBus::BroadcastResult(success, &Physics::CollisionRequests::TryGetCollisionLayerByName, layerName, collisionLayer);
|
|
if (success)
|
|
{
|
|
controller->SetCollisionLayer(collisionLayer);
|
|
}
|
|
}
|
|
}
|
|
|
|
AZStd::string CharacterControllerComponent::GetCollisionLayerName()
|
|
{
|
|
AZStd::string layerName;
|
|
auto* controller = GetControllerConst();
|
|
if (controller == nullptr)
|
|
{
|
|
return layerName;
|
|
}
|
|
|
|
Physics::CollisionRequestBus::BroadcastResult(
|
|
layerName, &Physics::CollisionRequests::GetCollisionLayerName, controller->GetCollisionLayer());
|
|
return layerName;
|
|
}
|
|
|
|
void CharacterControllerComponent::SetCollisionGroup(const AZStd::string& groupName, AZ::Crc32 colliderTag)
|
|
{
|
|
auto* controller = GetController();
|
|
if (controller == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (Physics::Utils::FilterTag(controller->GetColliderTag(), colliderTag))
|
|
{
|
|
bool success = false;
|
|
AzPhysics::CollisionGroup collisionGroup;
|
|
Physics::CollisionRequestBus::BroadcastResult(success, &Physics::CollisionRequests::TryGetCollisionGroupByName, groupName, collisionGroup);
|
|
if (success)
|
|
{
|
|
controller->SetCollisionGroup(collisionGroup);
|
|
}
|
|
}
|
|
}
|
|
|
|
AZStd::string CharacterControllerComponent::GetCollisionGroupName()
|
|
{
|
|
AZStd::string groupName;
|
|
auto* controller = GetControllerConst();
|
|
if (controller == nullptr)
|
|
{
|
|
return groupName;
|
|
}
|
|
|
|
Physics::CollisionRequestBus::BroadcastResult(
|
|
groupName, &Physics::CollisionRequests::GetCollisionGroupName, controller->GetCollisionGroup());
|
|
return groupName;
|
|
}
|
|
|
|
void CharacterControllerComponent::ToggleCollisionLayer(const AZStd::string& layerName, AZ::Crc32 colliderTag, bool enabled)
|
|
{
|
|
auto* controller = GetController();
|
|
if (controller == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (Physics::Utils::FilterTag(controller->GetColliderTag(), colliderTag))
|
|
{
|
|
bool success = false;
|
|
AzPhysics::CollisionLayer collisionLayer;
|
|
Physics::CollisionRequestBus::BroadcastResult(success, &Physics::CollisionRequests::TryGetCollisionLayerByName, layerName, collisionLayer);
|
|
if (success)
|
|
{
|
|
AzPhysics::CollisionLayer layer(layerName);
|
|
AzPhysics::CollisionGroup group = controller->GetCollisionGroup();
|
|
group.SetLayer(layer, enabled);
|
|
controller->SetCollisionGroup(group);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CharacterControllerComponent::OnPreSimulate(float deltaTime)
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->ApplyRequestedVelocity(deltaTime);
|
|
const AZ::Vector3 newPosition = controller->GetBasePosition();
|
|
AZ::TransformBus::Event(GetEntityId(), &AZ::TransformBus::Events::SetWorldTranslation, newPosition);
|
|
}
|
|
}
|
|
|
|
const PhysX::CharacterController* CharacterControllerComponent::GetControllerConst() const
|
|
{
|
|
if (m_controllerBodyHandle == AzPhysics::InvalidSimulatedBodyHandle || m_attachedSceneHandle == AzPhysics::InvalidSceneHandle)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
|
{
|
|
return azdynamic_cast<PhysX::CharacterController*>(
|
|
sceneInterface->GetSimulatedBodyFromHandle(m_attachedSceneHandle, m_controllerBodyHandle));
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
PhysX::CharacterController* CharacterControllerComponent::GetController()
|
|
{
|
|
return const_cast<PhysX::CharacterController*>(static_cast<const CharacterControllerComponent&>(*this).GetControllerConst());
|
|
}
|
|
|
|
void CharacterControllerComponent::CreateController()
|
|
{
|
|
if (IsPhysicsEnabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
Physics::DefaultWorldBus::BroadcastResult(m_attachedSceneHandle, &Physics::DefaultWorldRequests::GetDefaultSceneHandle);
|
|
if (m_attachedSceneHandle == AzPhysics::InvalidSceneHandle)
|
|
{
|
|
AZ_Error("PhysX Character Controller Component", false, "Failed to retrieve default scene.");
|
|
return;
|
|
}
|
|
|
|
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;
|
|
});
|
|
|
|
// 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;
|
|
|
|
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
|
|
if (sceneInterface != nullptr)
|
|
{
|
|
m_controllerBodyHandle = sceneInterface->AddSimulatedBody(m_attachedSceneHandle, m_characterConfig.get());
|
|
}
|
|
if (m_controllerBodyHandle == AzPhysics::InvalidSimulatedBodyHandle)
|
|
{
|
|
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(m_attachedSceneHandle, m_onSimulatedBodyRemovedHandler);
|
|
}
|
|
|
|
CharacterControllerRequestBus::Handler::BusConnect(GetEntityId());
|
|
|
|
if (m_characterConfig->m_applyMoveOnPhysicsTick)
|
|
{
|
|
m_preSimulateHandler = AzPhysics::SystemEvents::OnPresimulateEvent::Handler(
|
|
[this](float deltaTime)
|
|
{
|
|
OnPreSimulate(deltaTime);
|
|
}
|
|
);
|
|
|
|
if (auto* physXSystem = GetPhysXSystem())
|
|
{
|
|
physXSystem->RegisterPreSimulateEvent(m_preSimulateHandler);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CharacterControllerComponent::DisableController()
|
|
{
|
|
if (auto* controller = GetController())
|
|
{
|
|
controller->DisablePhysics();
|
|
|
|
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
|
{
|
|
sceneInterface->RemoveSimulatedBody(m_attachedSceneHandle, controller->m_bodyHandle);
|
|
}
|
|
|
|
DestroyController();
|
|
}
|
|
}
|
|
|
|
void CharacterControllerComponent::DestroyController()
|
|
{
|
|
m_controllerBodyHandle = AzPhysics::InvalidSimulatedBodyHandle;
|
|
m_attachedSceneHandle = AzPhysics::InvalidSceneHandle;
|
|
m_preSimulateHandler.Disconnect();
|
|
m_onSimulatedBodyRemovedHandler.Disconnect();
|
|
CharacterControllerRequestBus::Handler::BusDisconnect();
|
|
}
|
|
} // namespace PhysX
|