From d436b71ef5d888e67d0d787596bc6fe31bbb765f Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 31 May 2021 13:30:45 +0200 Subject: [PATCH] Fix CharacterController still colliding after being disabled at runtime --- .../Physics/Colliders/CharacterController.cpp | 75 +++++++++++++++---- .../Physics/Colliders/CharacterController.h | 41 ++++------ 2 files changed, 74 insertions(+), 42 deletions(-) diff --git a/Source/Engine/Physics/Colliders/CharacterController.cpp b/Source/Engine/Physics/Colliders/CharacterController.cpp index ef856bf79..68fd8bfbe 100644 --- a/Source/Engine/Physics/Colliders/CharacterController.cpp +++ b/Source/Engine/Physics/Colliders/CharacterController.cpp @@ -30,6 +30,11 @@ CharacterController::CharacterController(const SpawnParams& params) static_assert(sizeof(_filterData) == sizeof(PxFilterData), "Invalid filter data size."); } +float CharacterController::GetRadius() const +{ + return _radius; +} + void CharacterController::SetRadius(const float value) { if (Math::NearEqual(value, _radius)) @@ -41,6 +46,11 @@ void CharacterController::SetRadius(const float value) UpdateBounds(); } +float CharacterController::GetHeight() const +{ + return _height; +} + void CharacterController::SetHeight(const float value) { if (Math::NearEqual(value, _height)) @@ -52,6 +62,11 @@ void CharacterController::SetHeight(const float value) UpdateBounds(); } +float CharacterController::GetSlopeLimit() const +{ + return _slopeLimit; +} + void CharacterController::SetSlopeLimit(float value) { value = Math::Clamp(value, 0.0f, 89.0f); @@ -100,6 +115,11 @@ void CharacterController::SetUpDirection(const Vector3& up) _upDirection = up; } +float CharacterController::GetMinMoveDistance() const +{ + return _minMoveDistance; +} + Vector3 CharacterController::GetUpDirection() const { return _controller ? P2C(_controller->getUpDirection()) : _upDirection; @@ -115,6 +135,16 @@ Vector3 CharacterController::GetVelocity() const return _controller ? P2C(_controller->getActor()->getLinearVelocity()) : Vector3::Zero; } +bool CharacterController::IsGrounded() const +{ + return (static_cast(_lastFlags) & static_cast(CollisionFlags::Below)) != 0; +} + +CharacterController::CollisionFlags CharacterController::GetFlags() const +{ + return _lastFlags; +} + CharacterController::CollisionFlags CharacterController::SimpleMove(const Vector3& speed) { const float deltaTime = Time::GetCurrentSafe()->DeltaTime.GetTotalSeconds(); @@ -178,7 +208,7 @@ void CharacterController::OnDebugDrawSelected() #endif -void CharacterController::CreateActor() +void CharacterController::CreateController() { ASSERT(_controller == nullptr && _shape == nullptr); @@ -218,6 +248,18 @@ void CharacterController::CreateActor() UpdateBounds(); } +void CharacterController::DeleteController() +{ + if (_controller) + { + _shape->userData = nullptr; + _controller->getActor()->userData = nullptr; + _controller->release(); + _controller = nullptr; + } + _shape = nullptr; +} + void CharacterController::UpdateSize() const { if (_controller) @@ -313,7 +355,8 @@ void CharacterController::UpdateLayerBits() void CharacterController::BeginPlay(SceneBeginData* data) { - CreateActor(); + if (IsActiveInHierarchy()) + CreateController(); // Skip collider base Actor::BeginPlay(data); @@ -325,26 +368,28 @@ void CharacterController::EndPlay() Actor::EndPlay(); // Remove controller - if (_controller) - { - _shape->userData = nullptr; - _controller->getActor()->userData = nullptr; - _controller->release(); - _controller = nullptr; - } - _shape = nullptr; + DeleteController(); } void CharacterController::OnActiveInTreeChanged() { // Skip collider base Actor::OnActiveInTreeChanged(); +} - // Clear velocities and the forces on disabled - if (!IsActiveInHierarchy() && _controller) - { - // TODO: sleep actor? clear forces? - } +void CharacterController::OnEnable() +{ + if (_controller == nullptr) + CreateController(); + + Collider::OnEnable(); +} + +void CharacterController::OnDisable() +{ + Collider::OnDisable(); + + DeleteController(); } void CharacterController::OnParentChanged() diff --git a/Source/Engine/Physics/Colliders/CharacterController.h b/Source/Engine/Physics/Colliders/CharacterController.h index 5b4dd3f49..5fece3195 100644 --- a/Source/Engine/Physics/Colliders/CharacterController.h +++ b/Source/Engine/Physics/Colliders/CharacterController.h @@ -71,15 +71,11 @@ private: uint32 _filterData[4]; public: - /// /// Gets the radius of the sphere, measured in the object's local space. The sphere radius will be scaled by the actor's world scale. /// API_PROPERTY(Attributes="EditorOrder(100), DefaultValue(50.0f), EditorDisplay(\"Collider\")") - FORCE_INLINE float GetRadius() const - { - return _radius; - } + float GetRadius() const; /// /// Sets the radius of the sphere, measured in the object's local space. The sphere radius will be scaled by the actor's world scale. @@ -90,10 +86,7 @@ public: /// Gets the height of the capsule, measured in the object's local space. The capsule height will be scaled by the actor's world scale. /// API_PROPERTY(Attributes="EditorOrder(110), DefaultValue(150.0f), EditorDisplay(\"Collider\")") - FORCE_INLINE float GetHeight() const - { - return _height; - } + float GetHeight() const; /// /// Sets the height of the capsule, measured in the object's local space. The capsule height will be scaled by the actor's world scale. @@ -104,10 +97,7 @@ public: /// Gets the slope limit (in degrees). Limits the collider to only climb slopes that are less steep (in degrees) than the indicated value. /// API_PROPERTY(Attributes="EditorOrder(210), DefaultValue(45.0f), Limit(0, 100), EditorDisplay(\"Character Controller\")") - FORCE_INLINE float GetSlopeLimit() const - { - return _slopeLimit; - } + float GetSlopeLimit() const; /// /// Sets the slope limit (in degrees). Limits the collider to only climb slopes that are less steep (in degrees) than the indicated value. @@ -151,10 +141,7 @@ public: /// Gets the minimum move distance of the character controller. The minimum traveled distance to consider. If traveled distance is smaller, the character doesn't move. This is used to stop the recursive motion algorithm when remaining distance to travel is small. /// API_PROPERTY(Attributes="EditorOrder(230), DefaultValue(0.0f), Limit(0, 1000), EditorDisplay(\"Character Controller\")") - FORCE_INLINE float GetMinMoveDistance() const - { - return _minMoveDistance; - } + float GetMinMoveDistance() const; /// /// Sets the minimum move distance of the character controller.The minimum traveled distance to consider. If traveled distance is smaller, the character doesn't move. This is used to stop the recursive motion algorithm when remaining distance to travel is small. @@ -171,18 +158,12 @@ public: /// /// Gets a value indicating whether this character was grounded during last move call grounded. /// - API_PROPERTY() FORCE_INLINE bool IsGrounded() const - { - return (static_cast(_lastFlags) & static_cast(CollisionFlags::Below)) != 0; - } + API_PROPERTY() bool IsGrounded() const; /// /// Gets the current collision flags. Tells which parts of the character capsule collided with the environment during the last move call. It can be used to trigger various character animations. /// - API_PROPERTY() FORCE_INLINE CollisionFlags GetFlags() const - { - return _lastFlags; - } + API_PROPERTY() CollisionFlags GetFlags() const; public: @@ -203,7 +184,6 @@ public: /// /// Gets the native PhysX rigid actor object. /// - /// The PhysX dynamic rigid actor. PxRigidDynamic* GetPhysXRigidActor() const; protected: @@ -211,7 +191,12 @@ protected: /// /// Creates the physics actor. /// - void CreateActor(); + void CreateController(); + + /// + /// Deletes the physics actor. + /// + void DeleteController(); /// /// Updates the character height and radius. @@ -248,6 +233,8 @@ protected: void DrawPhysicsDebug(RenderView& view) override; #endif void OnActiveInTreeChanged() override; + void OnEnable() override; + void OnDisable() override; void OnParentChanged() override; void OnTransformChanged() override; };