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 애니메이션을 선택하고, 물리 기반 블렌딩으로 연결하세요.