영상을 불러오지 못했습니다

UE4 Skeletal Mesh Scale 복원 후 래그돌 물리가 깨질 때

855 단어
4 분
UE4 Skeletal Mesh Scale 복원 후 래그돌 물리가 깨질 때

이 글은 2021년 5월의 Unreal Engine 4.26·PhysX 프로젝트에서 관찰한 문제를 당시 기준으로 옮긴 기록이다. 모든 scale 변경에서 발생하는 일반 법칙이 아니라, 거의 0까지 축소했던 Skeletal Mesh를 복원한 뒤 physics simulation을 켜는 특정 흐름의 해결 사례다.

Zombie가 땅에서 기어 나오는 애니메이션에서 한 frame이 튀는 현상을 가리기 위해, spawn 직후 Actor의 Skeletal Mesh scale을 0.001로 줄였다가 약 0.5초 뒤 원래 크기로 복원했다.

그 뒤 사망 처리에서 ragdoll을 활성화하면 physics body가 비정상적으로 충돌하며 시체가 심하게 떨거나 뒤틀렸다.

Skeletal Mesh scale 복원 뒤 래그돌이 비정상적으로 충돌하는 모습
Skeletal Mesh scale 복원 뒤 래그돌이 비정상적으로 충돌하는 모습

문제의 조건#

당시에는 아래 순서로 문제가 재현됐다.

  1. Skeletal Mesh scale을 거의 0에 가깝게 줄인다.
  2. 잠시 뒤 시각적 scale을 원래 크기로 복원한다.
  3. 사망 시 SetAllBodiesSimulatePhysics(true)로 ragdoll을 켠다.
  4. physics body가 복원된 mesh 크기와 맞지 않는 듯한 충돌이 발생한다.

Scale을 KINDA_SMALL_NUMBER, 즉 0.0001 부근 이하로 설정하면 warning도 확인됐다.

Scale3D is (nearly) zero

이 warning의 정확한 경계에 의존해서 코드를 작성하기보다, physics와 collision이 있는 Component를 거의 0으로 축소하는 흐름 자체를 피하는 편이 안전하다.

Physics State를 다시 만든다#

당시에는 scale을 복원하고 simulation을 시작하기 전에 Skeletal Mesh Component의 physics state를 다시 만들어 문제를 해결했다.

USkeletalMeshComponent* Mesh = GetMesh();
if (!Mesh)
{
return;
}
Mesh->SetRelativeScale3D(OriginalScale);
Mesh->RecreatePhysicsState();
Mesh->SetAllBodiesSimulatePhysics(true);

UE 4.27의 UActorComponent::RecreatePhysicsState() 구현은 아래와 같았다.

void UActorComponent::RecreatePhysicsState()
{
DestroyPhysicsState();
if (IsRegistered())
{
CreatePhysicsState();
}
}

기존 PhysX state를 제거한 뒤, Component가 등록된 상태라면 현재 Component 설정과 transform을 기준으로 다시 생성하는 구조다. 이 사례에서는 축소된 시점의 body state가 남아 있던 문제를 scale 복원 이후의 상태로 재구성했다.

호출 순서#

원래 scale로 돌린 뒤, physics simulation을 켜기 전에 호출해야 한다.

void AZombieCharacter::EnableRagdoll()
{
USkeletalMeshComponent* Mesh = GetMesh();
if (!Mesh)
{
return;
}
Mesh->SetRelativeScale3D(OriginalMeshScale);
Mesh->SetCollisionProfileName(TEXT("Ragdoll"));
Mesh->RecreatePhysicsState();
Mesh->SetAllBodiesSimulatePhysics(true);
}

최종 scale과 collision 설정이 반영된 state를 만든 뒤 simulation을 시작해야 한다.

주의할 점#

RecreatePhysicsState()는 가벼운 transform update가 아니다. body를 파괴하고 다시 만들기 때문에 사용 범위를 좁혀야 한다.

  • Tick마다 호출하지 않는다.
  • 기존 velocity, constraint와 접촉 상태를 이어 가야 하는 도중에는 사용하지 않는다.
  • Component가 등록되지 않았다면 함수는 state를 다시 만들지 않는다.
  • multiplayer라면 server와 client 중 어느 쪽에서 physics를 실제로 simulation하는지 구분한다.
  • scale 변경만으로 문제가 재현되지 않는다면 무조건 이 함수를 추가하지 않는다.

이 해결책은 이미 어긋난 physics state를 복구하는 방법이다. 원래 문제였던 frame popping은 scale을 거의 0으로 만들기보다 animation pose·visibility·spawn 연출을 조정해 해결하는 편이 근본적이다. 다만 당시 프로젝트처럼 해당 흐름을 즉시 바꾸기 어려운 상황에서는 simulation 직전의 RecreatePhysicsState()가 유효한 우회책이었다.

참고 자료#

글 공유하기

이 글이 도움이 되셨다면 다른 사람과 공유해 주세요!

UE4 Skeletal Mesh Scale 복원 후 래그돌 물리가 깨질 때
https://velog.io/@hon454/SkeletalMesh의-Scale-조정-시-물리가-정상적으로-작동하지-않는-문제
작성자
Jihoon Jeon
게시일
2021-05-17
라이선스
CC BY-NC-SA 4.0
관련 게시글스마트
1
Unreal Engine PIE에서 클라이언트와 서버 값을 한 줄로 비교하기
Unreal EnginePIE에서 클라이언트 코드가 같은 프로세스의 서버 월드와 서버 측 PlayerController를 찾아 위치·속도를 한 줄로 비교하는 에디터 전용 디버그 코드와, 네트워크 에뮬레이션으로 확인한 측정 결과를 정리합니다.
2
UE4 다른 모듈의 UInterface 캐스팅에서 LNK1120이 발생할 때
Unreal EngineUE 4.26에서 다른 모듈의 UInterface를 사용할 때 GetPrivateStaticClass 링크 오류가 발생한 원인과 두 인터페이스 타입에 모듈 API 매크로를 적용하는 방법을 정리합니다.
3
면접 오답노트: 말하지 못한 주요 개념, Net Relevancy
Unreal Engine면접에서 제대로 답하지 못한 Net Relevancy를 다시 정리한다. AActor::IsNetRelevantFor의 판정 순서와 문서와 다른 부분, Owner가 판정을 바꾸는 방식, 연관성을 잃고 되찾을 때 RelevantTimeout과 액터 파괴, BeginPlay, OnRep, RPC에 생기는 일, ForceNetRelevant와 Replication Graph, Iris에서의 주의점, Dormancy, Priority와의 차이를 다룬다.
4
휴면 액터 깨우기: FlushNetDormancy, ForceNetUpdate, SetNetDormancy
Unreal EngineUE 5.8.3 엔진 소스 기준으로 FlushNetDormancy, ForceNetUpdate, SetNetDormancy가 각각 무엇을 바꾸는지 비교한다. 휴면 정책과 휴면 상태의 차이, ForceNetUpdate가 덤으로 하는 flush가 빠지는 조건, 값을 바꾼 뒤 깨우면 FastArray 변경이 사라지는 문제, 이를 막는 setter 패턴과 Push Model을 함께 쓸 때의 주의점을 정리한다.
5
Unreal Engine - Replication Graph
Unreal EngineUE 5.8.3 소스와 테스트 프로젝트 실측으로 Replication Graph가 기본 드라이버의 무엇을 줄이고 무엇을 줄이지 않는지 확인한다. 액터 5,000개와 클라이언트 16개까지의 측정, 효과가 있는 설정값과 이름과 반대로 동작하는 설정값, 커스텀 그래프의 라우팅과 Team Node, 5.8.3에서 재현한 버그 다섯 가지, 도입 기준과 Iris와의 관계를 다룬다.
무작위 게시글무작위

댓글

Profile Image of the Author
Jihoon Jeon
안녕하세요! 서브컬처와 자전거를 사랑하는 개발자 전지훈입니다.
공지사항
제 블로그에 오신 것을 환영합니다! 예시 공지입니다.
카테고리
태그
최신 일상
사이트 통계
게시글
73
카테고리
10
태그
143
총 단어 수
133,527
운영 일수
0일
최근 활동
0일 전
사이트 정보
빌드 플랫폼
GitHub Actions
블로그 버전
Firefly v6.16.9
라이선스
CC BY-NC-SA 4.0
목차