PART 6 · 강의 2/3

Ragdoll과 블렌딩

SetSimulatePhysics, PhysicsBlendWeight, 래그돌 전환과 GetUp 시스템을 심층 분석합니다.

SECTION 01

래그돌 시스템 기초

전신 물리 시뮬레이션으로 전환하는 래그돌 메커니즘

래그돌(Ragdoll)은 캐릭터의 모든 본에 물리 시뮬레이션을 활성화하여 중력과 충돌에 의해 자연스럽게 쓰러지는 효과입니다. 사망, 기절, 폭발 넉백 등에 사용됩니다.

C++
// 기본 래그돌 활성화 void AMyCharacter::EnableRagdoll() { USkeletalMeshComponent* Mesh = GetMesh(); // 1. 캡슐 콜리전 비활성화 (물리 바디가 대신) GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision); // 2. 이동 컴포넌트 비활성화 GetCharacterMovement()->DisableMovement(); GetCharacterMovement()->StopMovementImmediately(); // 3. 전신 물리 시뮬레이션 활성화 Mesh->SetSimulatePhysics(true); Mesh->SetCollisionProfileName(TEXT("Ragdoll")); // 4. 메시를 루트로 변경 (물리가 위치 제어) Mesh->SetEnableGravity(true); Mesh->WakeAllRigidBodies(); // 5. 초기 속도 전달 (이동 관성 유지) FVector Velocity = GetCharacterMovement()->Velocity; Mesh->SetPhysicsLinearVelocity(Velocity); } // 래그돌 비활성화 void AMyCharacter::DisableRagdoll() { USkeletalMeshComponent* Mesh = GetMesh(); Mesh->SetSimulatePhysics(false); Mesh->SetCollisionProfileName(TEXT("CharacterMesh")); GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); GetCharacterMovement()->SetMovementMode(MOVE_Walking); }
래그돌 전환 시 주의사항

래그돌 활성화 시 메시의 위치가 캡슐과 분리됩니다. 래그돌 해제 후에는 메시의 현재 위치로 캡슐을 이동시켜야 합니다. 그렇지 않으면 캐릭터가 래그돌 이전 위치로 순간이동합니다.

SECTION 02

애니메이션-래그돌 블렌딩

PhysicsBlendWeight를 활용한 점진적 래그돌 전환

갑작스러운 래그돌 전환은 시각적으로 부자연스럽습니다. PhysicsBlendWeight를 0에서 1로 점진적으로 증가시키면 애니메이션에서 래그돌로 부드럽게 전환됩니다.

블렌딩 타임라인
PhysicsBlendWeight 1.0 │ ┌───────────── 완전 래그돌 │ / │ / 0.5 │ / ← 블렌딩 구간 (0.3~0.5초) │ / │ / 0.0 │───────────┘ ← 순수 애니메이션 └────────────────────────────────── 시간 t=0 t=0.1 t=0.3 t=0.5 (피격) (임펄스) (블렌딩) (래그돌)
C++
// 점진적 래그돌 블렌딩 void AMyCharacter::BlendToRagdoll(float Duration) { USkeletalMeshComponent* Mesh = GetMesh(); // 물리 시뮬레이션 활성화 (블렌드 웨이트 0에서 시작) Mesh->SetAllBodiesSimulatePhysics(true); Mesh->SetAllBodiesPhysicsBlendWeight(0.f); // 블렌딩 시작 BlendDuration = Duration; BlendElapsed = 0.f; bIsBlendingToRagdoll = true; } void AMyCharacter::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (bIsBlendingToRagdoll) { BlendElapsed += DeltaTime; float Alpha = FMath::Clamp(BlendElapsed / BlendDuration, 0.f, 1.f); // Ease-In 커브 적용 float SmoothedAlpha = FMath::InterpEaseIn(0.f, 1.f, Alpha, 2.f); GetMesh()->SetAllBodiesPhysicsBlendWeight(SmoothedAlpha); if (Alpha >= 1.f) { bIsBlendingToRagdoll = false; // 완전 래그돌 상태로 전환 FinalizeRagdoll(); } } }
SECTION 03

GetUp 시스템

래그돌에서 애니메이션으로 복귀하는 GetUp 구현

GetUp 흐름
래그돌 정지 감지
앞/뒤 방향 판단
캡슐 이동
블렌딩 (물리→애님)
GetUp Montage
C++
// GetUp 시스템 구현 void AMyCharacter::TryGetUp() { USkeletalMeshComponent* Mesh = GetMesh(); // 1. 래그돌 정지 여부 확인 FVector PelvisVelocity = Mesh->GetPhysicsLinearVelocity(FName("pelvis")); if (PelvisVelocity.Size() > StopThreshold) return; // 아직 움직이는 중 // 2. 엎드림/뒤집힘 판단 FVector PelvisUp = Mesh->GetBoneQuaternion(FName("pelvis")) .GetUpVector(); bool bFaceDown = FVector::DotProduct(PelvisUp, FVector::UpVector) < 0.f; // 3. 캡슐을 골반 위치로 이동 FVector PelvisLocation = Mesh->GetBoneLocation(FName("pelvis")); FVector CapsuleBottom = PelvisLocation; CapsuleBottom.Z = FindFloorZ(PelvisLocation); // 바닥 높이 찾기 SetActorLocation(CapsuleBottom); // 4. 래그돌 해제 및 블렌딩 Mesh->SetSimulatePhysics(false); GetCharacterMovement()->SetMovementMode(MOVE_Walking); GetCapsuleComponent()->SetCollisionEnabled( ECollisionEnabled::QueryAndPhysics); // 5. GetUp Montage 재생 UAnimMontage* GetUpMontage = bFaceDown ? GetUpFaceDownMontage : GetUpFaceUpMontage; UAnimInstance* AnimInst = Mesh->GetAnimInstance(); AnimInst->Montage_Play(GetUpMontage, 1.0f); } // 래그돌 정지 감지 (매 프레임 체크) void AMyCharacter::CheckRagdollStopped() { if (!bIsRagdoll) return; FVector Velocity = GetMesh()->GetPhysicsLinearVelocity(FName("pelvis")); if (Velocity.SizeSquared() < StopThresholdSq) { StoppedTime += GetWorld()->GetDeltaSeconds(); if (StoppedTime > MinStopDuration) // 0.5초 이상 정지 { TryGetUp(); } } else { StoppedTime = 0.f; } }
Pose Snapshot 활용

래그돌 해제 직전의 포즈를 Pose Snapshot으로 캡처하고, GetUp Montage의 첫 프레임과 블렌딩하면 더 자연스러운 전환을 만들 수 있습니다. SavePoseSnapshot으로 현재 포즈를 저장하고, AnimBP에서 Pose Snapshot 노드로 읽어 블렌딩합니다.

SECTION 04

부분 래그돌과 하이브리드 패턴

상체만 래그돌, 다리는 애니메이션 유지하는 하이브리드 기법

상체 래그돌

spine_01 이상만 SimulatePhysics 활성화. 다리는 로코모션 애니메이션 유지. 피격 반응이나 폭발 넉백에 효과적입니다.

활성 래그돌(Active Ragdoll)

Physical Animation + 래그돌 조합. 물리 모터가 걷기/서기 포즈를 추종하면서, 외력에 반응하여 비틀거리는 효과를 만듭니다.

사망 래그돌

전신 래그돌 + 초기 임펄스. 사망 원인(총알 방향, 폭발 위치)에 따라 다른 임펄스를 적용하여 다양한 사망 연출을 만듭니다.

래그돌 + Constraint

특정 본에 PhysicsConstraint를 걸어 래그돌의 움직임을 제한합니다. 매달리기, 잡기 등의 연출에 활용합니다.

SUMMARY

핵심 요약

  • 래그돌은 SetSimulatePhysics(true)로 전신 물리를 활성화하며, 캡슐 콜리전과 MovementComponent를 비활성화한다.
  • PhysicsBlendWeight를 점진적으로 변경하여 애니메이션 ↔ 래그돌 간 부드러운 전환을 구현한다.
  • GetUp 시스템: 정지 감지 → 방향 판단 → 캡슐 이동 → 물리 해제 → GetUp Montage 재생
  • Pose Snapshot으로 래그돌 포즈를 캡처하고 GetUp 애니메이션과 블렌딩하면 전환이 자연스럽다.
  • 부분 래그돌로 상체만 물리 반응, 하체는 애니메이션 유지하는 하이브리드가 가능하다.
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: 래그돌 전환 구현

캐릭터 사망 시 Set All Bodies Simulate Physics(true)로 래그돌을 활성화하세요. Set Collision Profile Name을 Ragdoll로 변경하고, Character Movement를 비활성화하세요. 사망 직전 캐릭터 속도를 물리 바디에 전달하여 자연스러운 전환을 만드세요.

실습 2: Physics Blend Weight 애니메이션

Set All Bodies Below Physics Blend Weight로 특정 본 이하의 물리 블렌드 비율을 0에서 1로 보간하세요. 상체는 애니메이션, 하체는 물리로 동작하는 반래그돌 상태를 구현하고, 넘어진 후 일어서는 Get Up 몽타주와 연결하세요.

심화 과제

래그돌에서 복귀하는 완전한 GetUp 시스템을 구현하세요. 래그돌 상태에서 pelvis 본 방향으로 엎드림/뒤로 넘어짐을 판별하고, 해당 방향의 GetUp 몽타주를 재생합니다. Physics Blend Weight를 1에서 0으로 부드럽게 보간하여 래그돌에서 애니메이션으로 자연스럽게 전환하세요.