diff --git a/Source/Engine/Physics/Colliders/CharacterController.cpp b/Source/Engine/Physics/Colliders/CharacterController.cpp
index 4315ce8ba..419b6b052 100644
--- a/Source/Engine/Physics/Colliders/CharacterController.cpp
+++ b/Source/Engine/Physics/Colliders/CharacterController.cpp
@@ -22,6 +22,7 @@ CharacterController::CharacterController(const SpawnParams& params)
, _radius(50.0f)
, _height(150.0f)
, _minMoveDistance(0.0f)
+ , _upDirection(Vector3::Up)
, _isUpdatingTransform(false)
, _nonWalkableMode(CharacterController::NonWalkableModes::PreventClimbing)
, _lastFlags(CollisionFlags::None)
@@ -82,6 +83,18 @@ void CharacterController::SetStepOffset(float value)
_controller->setStepOffset(value);
}
+void CharacterController::SetUpDirection(const Vector3& up)
+{
+ if (_controller)
+ _controller->setUpDirection(C2P(up));
+ _upDirection = up;
+}
+
+Vector3 CharacterController::GetUpDirection() const
+{
+ return _controller ? P2C(_controller->getUpDirection()) : _upDirection;
+}
+
void CharacterController::SetMinMoveDistance(float value)
{
_minMoveDistance = Math::Max(value, 0.0f);
@@ -180,6 +193,7 @@ void CharacterController::CreateActor()
// Create controller
_controller = (PxCapsuleController*)Physics::GetControllerManager()->createController(desc);
ASSERT(_controller);
+ _controller->setUpDirection(C2P(_upDirection));
const auto actor = _controller->getActor();
ASSERT(actor && actor->getNbShapes() == 1);
actor->getShapes(&_shape, 1);
@@ -363,6 +377,7 @@ void CharacterController::Serialize(SerializeStream& stream, const void* otherOb
SERIALIZE_MEMBER(Radius, _radius);
SERIALIZE_MEMBER(Height, _height);
SERIALIZE_MEMBER(MinMoveDistance, _minMoveDistance);
+ SERIALIZE_MEMBER(UpDirection, _upDirection);
}
void CharacterController::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
@@ -376,4 +391,5 @@ void CharacterController::Deserialize(DeserializeStream& stream, ISerializeModif
DESERIALIZE_MEMBER(Radius, _radius);
DESERIALIZE_MEMBER(Height, _height);
DESERIALIZE_MEMBER(MinMoveDistance, _minMoveDistance);
+ DESERIALIZE_MEMBER(UpDirection, _upDirection);
}
diff --git a/Source/Engine/Physics/Colliders/CharacterController.h b/Source/Engine/Physics/Colliders/CharacterController.h
index f850b9124..8ae992c59 100644
--- a/Source/Engine/Physics/Colliders/CharacterController.h
+++ b/Source/Engine/Physics/Colliders/CharacterController.h
@@ -65,6 +65,7 @@ private:
float _height;
float _minMoveDistance;
bool _isUpdatingTransform;
+ Vector3 _upDirection;
NonWalkableModes _nonWalkableMode;
CollisionFlags _lastFlags;
uint32 _filterData[4];
@@ -141,6 +142,17 @@ public:
///
API_PROPERTY() void SetStepOffset(float value);
+ ///
+ /// Gets the character up vector.
+ ///
+ API_PROPERTY(Attributes="EditorOrder(240), DefaultValue(true), EditorDisplay(\"Character Controller\")")
+ Vector3 GetUpDirection() const;
+
+ ///
+ /// Sets the character up vector.
+ ///
+ API_PROPERTY() void SetUpDirection(const Vector3& up);
+
///
/// 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.
///