UDN
Search public documentation:

RootMotionKR
English Translation
日本語訳
中国翻译

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 홈 > 애니메이션 > 루트 모션

루트 모션


문서 변경내역: Laurent Delayen 작성. 홍성진 번역.

개요


수학 공식을 사용해서 월드에 있는 액터를 움직일 수 있습니다. 차를 예로 들어 플레이어가 가속 페달을 밟으면 차의 속도가 증가되면서 그 위치가 업데이트될 것입니다. 거기서 다음과 같은 공식을 낼 수 있겠지요:

Velocity = Acceletation * DeltaTime; // 속도 = 가속도 * 경과시간
Position = Velocity * DeltaTime; // 위치 = 속도 * 경과시간

마찰이라든가 중력이라든가, 다른 여러가지 요인을 계산에 넣어 차의 움직임을 현실에 가깝게 만들 수 있습니다. 메카닉 오브젝트의 시뮬레이션을 정확히 하는 것은 꽤나 쉬운 편이지만, 오가닉 오브젝트는 차원이 달라집니다. 인간, 말, 원숭이같은 것을 예로 들어 봅시다. 그 운동은 매우 불규칙적이며 간단한 등식으로 환산하여 시뮬레이트할 수 있는 간단한 패턴을 따르지는 않습니다. 물론 언젠가는 게임에서 사용할 수 있는 현실적인 실시간 순차 운동을 만들어낼 수 있는 날이 오겠지만, 현재로서는 애니메이션으로 액터 운동을 돌리는 것이 가장 효율적인 해법입니다.

복잡한 운동을 애니메이션에 구워넣자는 것인데, 이 작업은 보통 스켈레탈 메시의 루트 본에 이루어지기에, 그 이름도 루트 모션이 된 것입니다. 그 루트 본 모션을 애니메이션에서 추출한 다음 게임 피직스로 전송하여 액터를 움직이는 것입니다.

애니메이션 시스템에 대한 개요는 Animation Overview KR 페이지를 참고하시기 바랍니다.

루트 모션에 사용할 스켈레탈 메시 준비하기


스켈레탈 메시가 루트 모션을 사용하도록 하려면, 루트 모션이 움직이는 애니메이션을 임포트합니다. 애님세트 에디터 에서 루트 모션을 미리볼 수 있습니다.

루트 모션 미리보기


애님세트 에디터에서 미리보려는 애니메이션을 선택합니다. 애님세트 에디터를 처음 접하시는 분들께서는 AnimSet Editor User Guide KR 페이지에서 시스템에 대해 간단히 참고해 보시기 바랍니다.

툴바에서 본 표시를 켰는지 확인하십시오. 다음 버튼으로 토글시킬 수 있습니다:

RootMotionTurnOnSkeleton.jpg

그러면 스켈레탈 메시의 본이 표시되며, 루트 본을 미리보기할 수도 있습니다.

RootStart.jpg

위는 첫 프레임의 메시이며, 아래는 애니메이션 중간의 메시입니다.

RootEnd.jpg

루트 모션을 나타내는 빨강 선을 볼 수 있는데, 애니메이션 첫 프레임과 현재 프레임 사이의 전환을 나타내는 것으로, 액터가 이동하게 될 거리를 나타냅니다.

보라색 선은 메시 원점으로의 루트 본 이동(translation)을 나타냅니다. 메시의 루트 본을 원점에서 시작하도록 할 필요는 없지만, 만약 그렇다면 빨간색과 보라색 선이 겹칠 것입니다.

게임에서 루트 모션 사용하기


게임에서 루트 모션을 사용하려면 가장 먼저, AnimNodeSequence 처럼 애니메이션을 재생할 수 있는 애니메이션 노드에서 그 옵션을 켜 줘야 합니다. 그 노드가 바로 애니메이션에 상대적인 루트 모션 옵션을 제어할 수 있는 곳입니다.

RootMotion_NodeSeq.jpg

위는 아주 간단한 애님트리 셋업 이미지로, 루트 모션 환경설정된 AnimNodeSequence 입니다.

RootMotion_NodeSeqParameters.jpg

루트 모션에 영향을 끼치는 AnimNodeSequence 파라미터는 이와 같습니다.

  • bZeroRootRotation - 루트 본 로테이션을 (0,0,0) 으로 고정합니다.
  • RootBoneOption[0] - 메시 로컬 스페이스 X 축에 대한 루트 본 옵션입니다.
  • RootBoneOption[1] - 메시 로컬 스페이스 Y 축에 대한 루트 본 옵션입니다.
  • RootBoneOption[2] - 메시 로컬 스페이스 Z 축에 대한 루트 본 옵션입니다.

각각의 축에 대한 루트 본 옵션에 가능한 것은:

  • RBA_Default - 디폴트 행위는 애니메이션에 루트 트랜슬레이션을 놔두고 오닝(owning) 액터 운동에 영향을 끼치지 않습니다.
  • RBA_Discard - 루트 본 운동은 버리고 첫 프레임 위치로 고정시킵니다.
  • RBA_Translate - 애니메이션 상의 루트 운동은 버리고 그 속도만 오닝 액터에 전송합니다.

이 옵션은 어느 축에도 영향을 끼칠 수 있습니다. 즉 X, Y 모션은 액터의 피직스에 전송하면서도 Z 는 애니메이션으로 유지하는 등의 작업을 할 수 있는 것입니다.

루트 모션에 대해 약간 언급해 보자면:

  • 여러 개의 루트 모션 애니메이션을 동시에 재생할 수도 있습니다. 루트 모션은 세 개 까지는 제대로 블렌딩되며, 그 이후로는 오닝 액터에 전송됩니다.
  • 루트 모션은 루핑(되풀이) 애니메이션을 제대로 지원합니다.

관련된 AnimNodeSequence 상에 루트 모션이 설정되고 나면, 액터는 결과 모션을 사용해야 합니다. 여기에도 여러가지 옵션이 있습니다.

  • bForceDiscardRootMotion - 루트 본을 0 로테이션 상태로 로컬 스페이스 원점에 강제 고정시킵니다.
  • bRootMotionModeChangeNotify - 오닝 액터에서 RootMotionModeChanged() 이벤트를 호출합니다.
  • RootMotionMode - 메시가 루트 모션을 사용하는 방법을 결정합니다.

RootMotionMode 로 가능한 것은:

  • RMM_Ignore - 루트 모션을 무시하고 아무것도 안합니다.
  • RMM_Translate - 루트 운동 델타를 가지고 액터를 바로 옮깁니다. 애니메이션 직후에 일어나며, 게임내 피직스를 사용하지 않습니다. (기어오르거나 미끌어지거나 떨어지지도 않으며, eventBump() 같은 스크립트 노티파이도 트리거하지 않습니다.)
  • RMM_Velocity - 루트 모션에서 속력을 추출하고, 액터의 최대 속도를 그것으로 제한시킵니다. 이 작업은 다음 프레임에 발생하며 오너 액터 피직스를 제한시킵니다. 즉 (기어오르고 미끌어지고 떨어지는) 피직스는 유지되고, 스크립트 노티파이 역시 계속 전송됩니다. 이 모드에서 언리얼 피직스는 계속해서 모션을 발생시키며, 애니메이션은 속도의 세기(즉 속력)을 일정 범위로 제한합니다. 상호작용 반응 시간 그리고/또는 이동 정밀도를 유지하고 싶을 때 (즉 길찾기(pathing), 특정 위치로 이동하기, 인풋 콘트롤러 반응시간 향상시키기 등에) 좋습니다.
  • RMM_Accel - 이 모드에서는 루트 모션을 언리얼 피직스에 직접 물려줍니다. 즉 길찾기나 인풋으로 설정된 폰의 가속도를 애니메이션의 루트 모션으로 덮어쓴다는 소리입니다. 언리얼 피직스는 애니메이션의 루트 모션에 일치시키기 위해 액터를 이동하려 합니다. 기어오르기, 미끌어지기, 떨어지기 등을 지원합니다. 월드의 콜리전과 지형도를 따르면서도 폰에 복잡하게 만든 모션을 일치시키고자 할 때 좋습니다.

심리스 트랜지션 (매끄러운 전환)


누구나 트랜지션 문제를 겪을 수밖에 없습니다. 어떻게 하면 게임내 피직스 운동에서 애니메이션 운동으로 매끄럽게 전환할 수 있을까요?

메시에 새로운 루트 모션 모드를 설정하면, 이 새로운 모드로 애니메이션을 처리한 지 딱 한 틱 이후에 효력이 나타납니다. 이미 처리되었을 수도 있는 게임내 피직스와의 콜리전을 방지하기 위함입니다. 상황에 따라 이러한 현상은 최대 한 두 프레임 정도 늦춰져서 때를 달리하여 일어날 수 있습니다만, 전환을 매끄럽게 술술 넘어가게 하는 방법이, 있습니다.

  • RMM_Translate - 모드가 언제 설정되었는지, 즉 게임내 피직스가 처리되기 전인지 후인지에 따라 달라집니다. 애니메이션이 계산되기 전 또는 후에도 설정 가능합니다. 확실한 것 한 가지는, 새로운 모드로 애니메이션이 처리되고서 정확히 1 틱 후에 루트 모션이 적용된다는 점입니다. 전환을 쉽게 하기 위해 루트 모션 모드가 언제 바뀌었는지를 알리는 bRootMotionModeChangeNotify 플랙이 있습니다. 이 플랙은 오닝 액터에서 이벤트를 트리거시키며, 그러면 전환을 연출할 수 있게 됩니다. 이 이벤트가 호출되면 루트 모션이 다음 틱에 적용되겠구나 확실히 알 수 있게 되고, 여기서 전환을 처리해 주면 되겠구나 마음먹으면 되는 것입니다. 예를 들어 여기서 피직스 운동(플레이어 인풋, 가속도, 속도)을 죽이고, 다음서부터는 루트 모션이 운동을 처리해 주겠구나 안심해도 되는 것입니다.

  • RMM_Velocity - 이 모드는 항상 한 프레임 랙을 두고 적용됩니다. 그러나 위와 마찬가지의 이유로, 애니메이션이 계산된 직후의 틱에 루트 모션이 적용되겠구나 장담할 수 있습니다. 이 모드로 전환하기는 훨씬 쉬운데, 액터의 강제 운동을 유지시킨 상태로 루트 모션의 속력 제한 효력이 발생하는 것을 기다리기만 하면 되기 때문입니다. 강제 운동은 여러가지 방법으로 가능한데, Controller.bPreciseDestination 을 사용하여 플레이어의 인풋을 강제하거나, 액터의 가속도/속도를 제어하거나 하면 됩니다.

루트 모션 사용 예제 (프로그래머용)


루트 모션을 사용한 예제는 이와 같습니다.

언리얼스크립트 RBA_Translate 예제

다음 샘플 코드는 폰에 루트 모션 점프 애니메이션을 재생하는 예제입니다. 예제는 예제일뿐, 그대로 컴파일하여 상처받지 맙시다!

YourPawn.uc
simulated function PlayJumpAnimation(AnimNodeSequence SeqNode)
{
   // 점프 애니메이션 재생
   SeqNode.SetAnim('Jump');
   SeqNode.PlayAnim(false, 1.f);

   // 애니메이션 노드에 루트 모션 켜기
   SeqNode.RootBoneOption[0] = RBA_Translate;
   SeqNode.RootBoneOption[1] = RBA_Translate;
   SeqNode.RootBoneOption[2] = RBA_Translate;

   // 애니메이션 노드더러 애니메이션 재생이 완료되면 알리라 이르라
   SeqNode.bCauseActorAnimEnd = TRUE;

   // 메시더러 액터 트렌슬레이션에 루트 모션을 사용하라 이르라
   Pawn.Mesh.RootMotionMode = RMM_Translate;

   // 메시더러 루트 모션이 언제 적용될지 알리라 이르라
   // 그때 짐이 피직스 운동에서 애니메이션 운동으로 매끄럽게 전환해 줄 터이니
   Pawn.Mesh.bRootMotionModeChangeNotify = TRUE;
}

simulated event RootMotionModeChanged(SkeletalMeshComponent SkelComp)
{
   /**
    * 루트 모션의 효력은 다음 프레임부터 나타날 터이니
    * 폰 운동을 죽이고 루트 모션을 들라 하라
    */
   if( SkelComp.RootMotionMode == RMM_Translate )
   {
      Velocity = Vect(0.f, 0.f, 0.f);
      Acceleration = Vect(0.f, 0.f, 0.f);
   }

   // 노티파이 끄고
   Pawn.Mesh.bRootMotionModeChangeNotify = false;
}

simulated event OnAnimEnd(AnimNodeSequence SeqNode)
{
   // 점프 완료

   // 루트 모션을 버리면 메시는 제자리에 고정될 테니
   // 다른 애니메이션을 적절히 블렌딩해 줘야 할 듯
   SeqNode.RootBoneOption[0] = RBA_Discard;
   SeqNode.RootBoneOption[1] = RBA_Discard;
   SeqNode.RootBoneOption[2] = RBA_Discard;

   // 메시더러 루트 모션을 그만 놓아주라 이르라
   Pawn.Mesh.RootMotionMode = RMM_Ignore;
}