본문 바로가기
PhysX/[NVIDIA] PhysX_Tutorial

10. PhysX - Character Controllers - 2

by 헛둘이 2023. 3. 5.

Walkable Parts & Invisible Walls

 
- 캐릭터는 어디로든 움직일 수 있으나 이게 항상 좋은 것은 아니다.
- 경사가 가파른 다각형 폴리곤 위에 올라타는 것을 방지해야 한다
- 사용자는 경사 각도 제한값을 정의하여 이를 자동으로 처리되게 할 수 있다.
(경사가 가파른 곳으로 이동하지 못하게 할 수 있다)
 
- 걸을 수 없는 지역에 닿을 때 일어나는 일을 정의하는 두 가지 모드가 있으며, 이는 PxControllerDesc::nonWalkableMode 열거형을 통해 정의할 수 있다.
 
1. PxControllerNonWalkableMode::ePREVENT_CLIMBING
: 캐릭터가 경사면에 오를 수 있지만 그 경사면을 타고 올라갈 수는 없고, 내려갈 수는 있다.
 
2. PxControllerNoneWalkableMode::ePREVENT_CLIMBING_AND_FORCE_SLIDING
: 캐릭터가 경사면에 부딪힌다면, 캐릭터는 경사면을 타고 미끄러지며 이동하게 된다.
: 그 경사면을 따라 미끄러지는 것을 강제로 유도한다.
 
- 경사각 제한은 PxControllerDesc::slopeLimit을 통해 정의된다.
- 이후에 PxController::getSlopeLimit() 함수를 통해 가져올 수 있다.
- 제한은 원하는 제한 각도의 코사인으로 표시됨 (아래 예제는 45도 경사제한)

slopeLimit = cosf(PxMath::degToRad(45.0f));

 
- slopeLimit = 0.0f로 설정하면 이 기능이 비활성화된다. (캐릭터는 어디로든 이동 가능)
- 이 기능은 항상 필요한 것은 아니고, 대신 레벨에 보이지 않는 벽을 놓아 플레이어의 움직임을 제한할 수 있다.
- CCT는 PxControllerDesc::invisibleWallHeight가 0이 아닐 경우 이런 벽을 생성한다.
- 이 매개변수는 높이를 제어하며, 사용자가 정의한 Up Vector 방향으로 확장된다.
- 그러나 이런 보이지 않는 벽은 걸어다닐 수 없는 폴리곤(위의 예시와 같이)이 발견되었을 때만 생성된다.
- 그런데 캐릭터는 이또한 뛰어넘을 수 있으므로 PxControllerDesc::maxJumpHeight 매개변수를 사용해서 바운딩 볼륨의 크기를 조절할 수 있다.
 
- 이 기능은 현재 정적 actor에 대해서만 사용할 수 있으며, 동적 actor나 kinematic actor에 대해서는 사용할 수 없다.
- 정적 구 또는 정적 캡슐에 대해서도 지원하지 않는다.
 


사용자 정의 장애물 (Obstacle Objects)

 
- 때로 SDK 객체를 만들기보단 CCT가 충돌할 장애물을 만드는 것이 편리할 때가 있음
(특정 구간을 클리어해야 다른 구간으로 넘어갈 수 있는 경우)
1. 장애물이 몇 프레임 동안만 존재하는 경우
2. 장애물이 캐릭터를 멈추기 위해서만 존재하는 경우
 
- 현재 캐릭터 컨트롤러는 Box, Capsule PxObstacle 객체를 지원한다.
- 즉 PxBoxObstacle 및 PxCapsuleObstacle이다.
- 이를 만드려면 다음 함수를 사용해서 PxObstacleContext 객체를 만든다.
 

PxObstacleContext* PxControllerManager::createObstacleContext()    = 0;

 
그런 다음 아래와 같이 장애물을 관리할 수 있다.

ObstacleHandle PxObstacleContext::addObstacle(const PxObstacle& obstacle) = 0;
bool PxObstacleContext::removeObstacle(ObstacleHandle handle) = 0;
bool PxObstacleContext::updateObstacle(ObstacleHandle handle, const PxObstacle& obstacle) = 0;

- 보통 updateObstacle 함수는 컨트롤러 move 직전에 호출된다.
 


Hit Callback

- PxUserControllerHitReport 객체는 컨트롤러의 진행 상황에 따라 정보를 검색하는 데 사용된다.
- 특히 캐릭터가 Shape나 다른 캐릭터 또는 사용자 정의 장애물 (Obstacle) 객체에 부딪힐 때 호출된다.
 
1. 캐릭터가 Shape에 부딪힐 때는 정적, 동적 Shape 모두에 대해
PxUserControllerHitReport::onShapeHit 콜백이 호출된다. (SampleBridges에서 설명되어있음)
- 다양한 충격 매개변수가 콜백에 전송되며, 이를 통해 소리를 재생하고, 렌더링하며, 힘을 적용하는 작업을 수행할 수 있다.
 
2. 캐릭터가 다른 캐릭터, 캐릭터 컨트롤러로 제어되는 다른 객체와 충돌하는 경우
PxUserControllerHitReport::onControllerHit 콜백이 호출된다. (예를 들어 플레이어와 NPC가 충돌하는 경우)
 
3. 캐릭터가 캐릭터 정의 장애물(Obstacle)에 충돌하는 경우
PxUserControllerHitReport::onObstacleHit 콜백이 호출된다.
 
 

Behavior Callback

- PxShape, PxController, PxObstacle에 충돌한 캐릭터의 동작을 사용자 지정하는 데 사용되는 PxControllerBehaviorCallback 객체
- 다음 함수에 의해 실행된다.
 

PxControllerBehaviorFlags PxControllerBehaviorCallback::getBehaviorFlags
    (const PxShape& shape, const PxActor& actor) = 0;
PxControllerBehaviorFlags PxControllerBehaviorCallback::getBehaviorFlags
    (const PxController& controller)             = 0;
PxControllerBehaviorFlags PxControllerBehaviorCallback::getBehaviorFlags
    (const PxObstacle& obstacle)                 = 0;

- 위 함수를 사용하면 플래그를 반환하는데, 
 
1. PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT
- 캐릭터가 서 있는 객체를 따라 이동할 수 있는지 여부를 정의
- 예를 들어 움직이는 물체 위에 있는 캐릭터는 그 물체와 함께 움직여야 한다.
- 이 플래그는 객체에서 컨트롤러로 전송되는 수평 변위를 제어한다
(수평변위는 보통 X, Z축을 얘기하지만 경사면을 오르는 등 특수한 경우 Y축도 포함될 수 있다)
 
2. PxControllerBehaviorFlag::eCCT_SLIDE
- 캐릭터가 객체 위에 서 있을 때 슬라이드 여부를 결정한다.
- 이전에 이야기했던 slopeLimit 대신에 사용할 수 있으며, 걸을 수 없는 객체가 아닌 걸을 수 없는 부분을 정의할 수 있다.
- 또한 캡슐 캐릭터가 플랫폼 가장자리에서 자동으로 떨어지도록 만들 수 있다.
 
3. PxControllerBehavierFlag::eCCT_USER_DEFINED_RIDE
- 단순히 컨트롤러가 객체 위에 오르는데 관련된 모든 내장 코드를 비활성화한다.
- 이 플래그는 이 문제를 CCT 라이브러리 외부에서 사용자가 처리하도록 한다.
 
 


Character Intersections : CCT vs 정적 Actor

 
- 캐릭터와 동적 Actor간의 상호작용을 구현하는 방법에 대한 문제가 있음
- 물리 엔진에선 bounding volume (캐릭터를 감싸는 박스 또는 캡슐)과 주변 물체 사이에서 접촉 지점에서 힘을 적용함으로써, 동적 Actor를 밀어내는 방식이 있지만, 이 방식은 실제 캐릭터와 물체 간의 상호작용을 제대로 모사하지 못한다.
- 또한 bounding volume의 크기가 실제 캐릭터보다 크면 캐릭터와 물체가 접촉하기전에 물체가 밀려나기 때문에 
캐릭터는 뭔가 자기장에 둘러싸인 것처럼 보일 수 있다.
 
- 따라서 이런 상호작용은 게임 플레이에 따라 결정되며, bounding volume에 의해 적용되는 힘은 bounding volume의 형태에 따라 달라지면 안된다.
- 이를 게임에 맞게 구현하기 위해서는 간단하게 PxUserControllerHitReport::onShapeHit 콜백을 사용해서 주변 물체에 인위적으로 힘을 적용하면 된다(SampleBridges 예제 참고)
 
- 또한 캐릭터 컨트롤러는 주변의 Shape를 결정하기 위해 overlap queries를 사용한다.
- 이 때 Shape는 PxShapeFlag::eSCENE_QUERY_SHAPE 플래그가 true로 설정되어 있어야 하며, 그렇지 않으면 CCT는 이들을 감지하지 못하고 통과한다. 
 


Hidden Kinematic Actors

 
- CCT 라이브러리는 각각 제어하는 캐릭터마다 숨겨진 kinematic actor를 생성한다.
- PxController::move 함수를 호출할 때 숨겨진 kinematic PxActor도 Scene에서 CCT 위치를 반영하여 업데이트된다.
 
- 사용자는 이런 숨겨진 엔티티를 알아야 한다.
- 왜냐면 Scene에서 직접 생성된 actor 수보다 더 많아서 '이게 뭐지' 할 수 있기 때문이다.
- 또한 scene-level 충돌 쿼리에서 이런 객체들이 발견되면 혼란스러울 수 있음
 
- 다음 함수를 사용해서 컨트롤러의 kinematic actor를 검색하는 것이 가능하다.

PxRigidDynamic* PxController::getActor() const;

 
- 그런 다음 PxRigidDynamic::userData 필드를 사용해서 이런 액터에 특수 태그를 지정할 수 있다.
- 이렇게 하면 충돌 쿼리나  contect report에서 CCT actor를 쉽게 식별하고 무시할 수 있다.

'PhysX > [NVIDIA] PhysX_Tutorial' 카테고리의 다른 글

12. Scene Query - 1  (0) 2023.03.21
11. Geometry Query  (0) 2023.03.20
9. PhysX - Character Controllers - 1  (1) 2023.03.04
8. PhysX - RigidBody Dynamics - 2  (0) 2023.03.04
7. PhysX - RigidBody Dynamics - 1  (0) 2023.03.04

댓글