PART 6 · 강의 2/3

Ragdoll 블렌딩

Physics Blend Weight를 활용한 부드러운 래그돌 전환과 회복

01

Physics Blend Weight

애니메이션과 물리 사이의 블렌드

Physics Blend Weight는 각 본이 애니메이션과 물리 시뮬레이션 사이에서 어느 쪽을 따를지 결정하는 가중치입니다. 0.0은 완전한 애니메이션, 1.0은 완전한 물리(래그돌)입니다.

C++ - Blend Weight 제어
// 전체 바디 Blend Weight 설정 void AMyCharacter::SetRagdollBlend(float BlendWeight) { GetMesh()->SetAllBodiesPhysicsBlendWeight(BlendWeight); } // 특정 본 이하만 Blend Weight 설정 void AMyCharacter::SetPartialRagdoll(FName BoneName, float Weight) { GetMesh()->SetAllBodiesBelowPhysicsBlendWeight( BoneName, Weight, false, true ); }
Blend Weight상태사용 시나리오
0.0완전 애니메이션일반 게임플레이
0.2~0.4미세한 물리 반응Physical Animation, 이차 운동
0.5~0.8강한 물리 영향히트 리액션, 기절
1.0완전 래그돌사망, 넉아웃
02

부드러운 래그돌 전환

즉각 전환 대신 점진적 블렌딩

C++ - 점진적 래그돌 전환
void AMyCharacter::StartRagdollTransition() { USkeletalMeshComponent* Mesh = GetMesh(); // 1. 물리 시뮬레이션 활성화 (아직 Blend Weight는 0) Mesh->SetAllBodiesSimulatePhysics(true); // 2. 캡슐 충돌 비활성화 GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision); // 3. 이동 비활성화 GetCharacterMovement()->DisableMovement(); // 4. 점진적으로 Blend Weight를 1.0으로 증가 CurrentBlendWeight = 0.0f; bTransitioningToRagdoll = true; } void AMyCharacter::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (bTransitioningToRagdoll) { CurrentBlendWeight = FMath::FInterpTo( CurrentBlendWeight, 1.0f, DeltaTime, 5.0f ); GetMesh()->SetAllBodiesPhysicsBlendWeight(CurrentBlendWeight); if (FMath::IsNearlyEqual(CurrentBlendWeight, 1.0f, 0.01f)) { CurrentBlendWeight = 1.0f; bTransitioningToRagdoll = false; } } }
03

래그돌에서 회복 (Get Up)

물리에서 애니메이션으로의 전환

C++ - Get Up (래그돌 회복)
void AMyCharacter::StartGetUp() { USkeletalMeshComponent* Mesh = GetMesh(); // 1. 래그돌의 현재 위치에서 Pelvis 본 위치 확인 FVector PelvisLocation = Mesh->GetBoneLocation(FName("pelvis")); // 2. 엎드려 있는지 뒤집어져 있는지 판별 FVector PelvisForward = Mesh->GetBoneQuaternion(FName("pelvis")) .GetForwardVector(); bool bFaceDown = FVector::DotProduct(PelvisForward, FVector::UpVector) < 0; // 3. 캐릭터 위치를 Pelvis로 이동 FVector NewActorLocation = PelvisLocation; NewActorLocation.Z = GetActorLocation().Z; // 지면 높이 유지 SetActorLocation(NewActorLocation); // 4. Blend Weight를 점진적으로 0으로 (Tick에서 처리) bTransitioningFromRagdoll = true; TargetBlendWeight = 0.0f; // 5. 적절한 Get Up 몽타주 재생 if (bFaceDown) PlayAnimMontage(GetUpFaceDownMontage); else PlayAnimMontage(GetUpFaceUpMontage); // 6. 블렌딩 완료 후 이동/캡슐 복원 (몽타주 Notify에서) } // 복원 함수 (AnimNotify에서 호출) void AMyCharacter::FinishGetUp() { GetMesh()->SetAllBodiesSimulatePhysics(false); GetMesh()->SetAllBodiesPhysicsBlendWeight(0.0f); GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); GetCharacterMovement()->SetMovementMode(MOVE_Walking); }
Get Up 시 주의사항

래그돌 상태의 메시 위치와 캡슐 위치가 다르므로, Get Up 전에 캡슐을 메시(Pelvis) 위치로 이동시켜야 합니다. 그렇지 않으면 캐릭터가 공중에서 일어서거나 벽 안에서 일어서는 문제가 발생합니다.

04

부분 래그돌 패턴

상체/하체 분리 래그돌

C++ - 부분 래그돌 사례
// 상체만 래그돌 (하체는 계속 걸어다님) void AMyCharacter::EnableUpperBodyRagdoll() { USkeletalMeshComponent* Mesh = GetMesh(); // spine_01 이하만 시뮬레이션 Mesh->SetAllBodiesBelowSimulatePhysics( FName("spine_01"), true, true ); // 상체만 Blend Weight 증가 Mesh->SetAllBodiesBelowPhysicsBlendWeight( FName("spine_01"), 0.8f, false, true ); } // 왼팔만 래그돌 (부상 연출) void AMyCharacter::EnableLeftArmRagdoll() { USkeletalMeshComponent* Mesh = GetMesh(); Mesh->SetAllBodiesBelowSimulatePhysics( FName("upperarm_l"), true, true ); Mesh->SetAllBodiesBelowPhysicsBlendWeight( FName("upperarm_l"), 1.0f, false, true ); }
SUMMARY

핵심 요약

  • Physics Blend Weight (0~1)로 애니메이션과 래그돌 사이를 부드럽게 블렌딩합니다.
  • 즉각 전환 대신 FInterpTo로 점진적 래그돌 전환이 자연스럽습니다.
  • Get Up 시 캡슐을 Pelvis 위치로 이동한 후 Get Up 몽타주를 재생합니다.
  • SetAllBodiesBelowSimulatePhysics()부분 래그돌(상체만, 팔만 등)을 구현합니다.
  • 래그돌 복원 후 반드시 캡슐 충돌, 이동 모드, Blend Weight를 원래대로 복원해야 합니다.
PRACTICE

도전 과제

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

실습 1: Ragdoll 블렌딩 기본 구현

캐릭터 사망 시 애니메이션에서 래그돌로 부드럽게 전환하는 시스템을 구현하세요. Physical Blend Weight를 0에서 1로 Lerp하여 자연스러운 전환을 만드세요.

실습 2: 부분 래그돌 블렌딩

상체만 래그돌로 전환하고 하체는 걷기 애니메이션을 유지하는 Partial Ragdoll을 구현하세요. Spine 본을 기준으로 블렌딩 가중치를 본 체인별로 다르게 적용하세요.

심화 과제: Get-Up 시스템

래그돌 상태에서 캐릭터가 일어나는 Get-Up 시스템을 구현하세요. 최종 포즈(앞/뒤 쓰러짐)를 감지하여 적절한 Get-Up 애니메이션을 선택하고, 물리 기반 블렌딩으로 연결하세요.