This document is about: QUANTUM 2
SWITCH TO

사용자 지정 애니메이터

Level 4
Available in the Gaming Circle and Industries Circle
Circle

소개

Quantum의 결정론적 애니메이터는 유니티의 메카님 컨트롤러의 베이킹 정보에 의해 동작합니다. 상태, 상태 간의 전이, 모션 클립 등과 같은 모든 구성에서 중요합니다.

사용할 때의 이점은 기기 간에 100% 동기화가 되도록 애니메이션을 제어할 수 있다는 점입니다. 롤백이 몇 프레임 전에 전환이 발생했음을 알리는 경우 애니메이션은 올바른 상태로 스냅 됩니다. 따라서 매우 정확한 틱 기반 애니메이션을 제공합니다. 이는 모든 클라이언트 시뮬레이션에서 애니메이션이 완벽하게 동기화되어야 하기 때문에 전투 게임과 일부 스포츠 게임에서 일반적으로 필요한 부분입니다.

애니메이터는 SDK 1.2.x 버전에 있었으나 Quantum SDK 2.0 버전 기본의 일부는 아닙니다. 하지만 유니티의 메카님에 대한 의존성과 유니티가 아직까지 새로운 안정적인 애니메이션 도구를 출시하지 않았기 때문에 애니메이터 도구의 개선을 중단하기로 결정했습니다.

이러한 이유로, 애니메이터를 quantum.state 및 quantum.systems 프로젝트로 가져올 수 있는 오픈 소스 코드로 설정했으며 필요에 따라 변경 및 재구축이 필요합니다.

이 문서에서는 사용자 지정 애니메이터가 프로젝트에서 불러오고 사용되는 방법을 설명합니다.

이 패키지는 Quantum SDK 2.0.0 A1 나이틀리 빌드 384로 최종 테스트 되었습니다.

사용자 지정 애니메이터 패키지

  1. 여기에서 사용자 지정 애니메이터 다운로드;
  2. 다운로드한 파일의 압축을 풀고QuantumCustomAnimator_stateQuantumCustomAnimator_systems 폴더의 내용을 quantum.code 프로젝트의 적절한 곳에 넣습니다
  3. 패키지는 CustomAnimatorUpdater를 초기화해주는 Frame.InitUser 메소드의 부분 구현과 함께 제공됩니다. 프로젝트에 이미 동일한 메소드의 부분 구현이 있는 경우 InitUser 내부에 InitializeAnimatorUpdater 메소드 호출을 포함시키기만 하면 되며 이 패키지의 Frame.User.cs 파일은 임포트 하지 마세요.
  4. 모든 것이 quantum.code 프로젝트 솔루션에 포함되었습니다
  5. 유니티에서 프로젝트에 QuantumCustomAnimator.unitypackage 를 임포트 합니다.

이렇게 하면 모든 빌드하고 실행하는 초기 단계가 완료됩니다. 이제 컴포넌트, 에셋 및 베이킹 도구를 실제로 사용하기 위해 다음과 같은 지침이 있습니다.

사용자 지정 애니메이터 사용하기

  • 컴포넌트 사용하기: 새로운 CustomAnimator 컴포넌트를 생성하고 코드로 엔티티에 추가하거나 유니티 상에서 엔티티 프로토 타입을 사용하여 추가합니다:

C#

var customAnimator = new CustomAnimator();
f.Set(fighter, customAnimator);
  • 유니티에서 CustomAnimatorGraph 타입의 새 데이터 에셋을 생성합니다. 유니티의 메카님 컨트롤러와 관련된 정보 저장을 담당하는 에셋입니다. 따라서 사용자 지정 애니메이터를 설정하기 위해 엔티티 프로토타입을 사용하는 경우 애니메이터 그래프 에셋의 AnimatorGraph 필드에서 참조할 수 있습니다. 코드에서 에셋을 찾으려면 다음과 같이 합니다.

var animatorGraphAsset = f.FindAsset<CustomAnimatorGraph>(assetGuid);

  • CustomAnimator 컴포넌트 초기화하기: 엔티티 프로토타입을 사용하고 있고 유니티에서 위에서 설명한 대로 CustomAnimatorGraph가 사용할 CustomAnimatorGraph를 이미 정의한 경우, CustomAnimatorSystem클래스에서 이미 대응 콜백을 사용하여 완료되었으므로 초기화할 필요가 없습니다. 그러나 엔티티 프로토타입을 사용하여 컴포넌트를 정의하지 않았거나 그래프 에셋을 선택하지 않은 경우에는 에셋을 찾아서 애니메이터로 다음과 같이 설정할 수 있습니다:

C#

CustomAnimator.SetCustomAnimatorGraph(&knight->CustomAnimator, animatorGraphAsset);
f.Set(fighter, customAnimator);
  • 유니티에서 수행되는 방식과 마찬가지로 Getter 및 Setter를 사용하여 애니메이터에 읽기/쓰기 합니다:

C#

// Getters
CustomAnimator.GetBoolean(frame, &fighter->Animator, "Defending");
CustomAnimator.GetFixedPoint(frame, &fighter->Animator, "Direction");
CustomAnimator.GetInteger(frame, &fighter->Animator, "State");

// Setters
CustomAnimator.SetBoolean(frame, &fighter->Animator, "Defending", true);
CustomAnimator.SetInteger(frame, &fighter->Animator, "Direction", 25);
CustomAnimator.SetFixedPoint(frame, &fighter->Animator, "Speed", FP._1);
CustomAnimator.SetTrigger(frame, &fighter->Animator, "Shoot");
  • Getter/setter 메소드에는 AnimatorGraph 또는 Variable ID가 이미 있는 경우 사용할 수 있는 일련의 메소드 오버로드가 있습니다. 한 번만 애니메이터 그래프를 가져와서 모든 getter/setter마다 다시 사용할 수 있기 때문에 매우 유용합니다. 그렇지 않으면 그래프 에셋을 모든 프레임에서 찾아야 합니다. 예를 들면:

    var animatorGraph = frame.FindAsset<CustomAnimatorGraph>(animator->animatorGraph.Id);
    CustomAnimator.SetTrigger(frame, animator, animatorGraph, "Shoot");
    CustomAnimator.SetFixedPoint(frame, animator, animatorGraph, "Speed", 0);
    CustomAnimator.SetBoolean(frame, animator, animatorGraph, "Defending", true);
    
    // This way you will only need to find the asset one time, instead of 3 times
    
  • 여기에서 유니티의 트리거 파라미터들은 불린 과같이 동작한다는 것을 알아채는 것이 중요합니다. 따라서 일부 파라미터를 트리거 하기 위해서 true로 설정하려면 다음 틱에 SetBoolean(&fighter→Animator, "MyTrigger", true)SetBoolean(&fighter→Animator, "MyTrigger", false)를 이용하여 트리거가 다시 활성화되지 않도록 해야 합니다. 패키지에 이미 애니메이션 시스템 전에 실행할 시스템이 포함되어 있어 모든 트리거 파라미터를 모든 틱에 false로 설정합니다. SystemSetup.cs 파일에 new CustomAnimatorResetTriggersSystem(), 코드를 삽입하기만 하면 됩니다.

  • 모든 AnimatorState 에는AssetRef 이 있으며 사용자 지정 에셋을 참조하기 위해 사용할 수 있습니다. 유니티에서 베이킹 프로세스를 확장하여 유니티의 애니메이터로부터 더 많은 정보를 얻고, 사용자 지정 에셋에 대한 정보를 저장하고, 상태를 참조할 수 있으므로 시뮬레이션에서 이 정보를 읽을 수 있습니다. 예를 들어 hitbox/hurtbox 정보를 FPAnimationCurves 형식으로 베이크 된 에셋을 생성할 수 있습니다. 유니티 이벤트 이름/시간을 에셋에 저장할 수 있으므로, 시뮬레이션에서 일부 애니메이션 이벤트가 발생할 때를 알 수 있습니다.

  • SystemSetup.cs 파일에 자신의 시스템 뒤에 이 코드 줄을 삽입합니다:

C#

new CustomAnimatorSystem(),
  • 유니티 Create/Quantum/CustomAnimatorGraph 컨텍스트 메뉴에서 사용자 지정 애니메이터 그래프 자산을 생성합니다;

다음은 기본 상태에서 보여주는 내용입니다:

Custom Animator Default
  • Controller 필드를 사용하여 유니티의 애니메이터 컨트롤러 에셋을 참조하고 Import Mecanim Controller 버튼을 누릅니다. 그런 다음 상태, 전환, 파라미터 등의 애니메이션 정보가 채워집니다:
Custom Animator Baked
  • EntityView 클래스를 열고, 다음 필드를 추가합니다:

    C#

    public CustomQuantumAnimator CustomQuantumAnimator;
    
  • 애니메이션이 될 GameObjects에 CustomQuantumAnimator 컴포넌트를 추가합니다. 물론 EntityPrefabRoot가 있어야 하므로 방금 추가한 컴포넌트를 위의 지침에 따라 만든 필드를 사용하여 참조하시기 바랍니다.

Custom Animator Game Object
  • EntitiyViewUpdater 클래스를 열고 OnUpdateView 메소드에는 활성 뷰에 대한 foreach 루프로 반복하는 것이 있습니다. 이제 사용자 지정 애니메이터 업데이트를 포함하고 있으므로 foreach는 다음과 같아야 합니다:

C#

// Iterate over all view instances and update components using only entities from current frame.
foreach (var kvp in _activeViews) {
    // ... updates 2D and 3D transforms

    // At the end of the foreach, add this.
    // This is responsible for actually animating the entity views
    if (instance.CustomQuantumAnimator)
    {
        if (game.Frames.Current.Unsafe.TryGetPointer<CustomAnimator>(instance.EntityRef, out var animator))
        {
            instance.CustomQuantumAnimator.Animate(game.Frames.Current, animator);
        }
    }
}
  • 마지막 단계는 객체에 유니티의 애니메이터 컴포넌트를 추가하는 것입니다. EntityPrefabRoot가 있는 동일한 객체에 배치하거나 하위 객체에 배치할 수 있습니다:
Custom Animator Mecanim Controller

이제 quantum 코드, 유니티 측에 필요한 교체 작업을 완료하고 유니티의 메카님 컨트롤러에서 직접 베이크 된 정보를 제공하는 CustomAnimatorGraph를 사용했으니 모두 준비되었습니다.

코드의 일부는 이미 간단한 주석과 함께 제공됩니다. Quantum 측면에는 AnimatorTransitions, AnimatorVariables(파라미터), Layers, Motion 등에 사용되는 AnimatorConditions와 같은 내부 상태 시스템과 관련된 모든 항목이 있습니다.

Unity 측에는 사용자 지정 애니메이터 그래프 에셋에 대한 사용자 정의 편집기 그리기와 관련된 코드와 충돌 정보용 FPAnimationCurves , 유니티의 애니메이션 이벤트 등과 같은 베이킹 프로세스를 담당하는 모든 코드가 있으며, 애니메이터 에셋에 더 많은 데이터를 굽기 위해 확장할 수 있습니다.

알려진 이슈

기본적으로 CustomAnimator에는 다음과 같은 제한 사항이 있습니다:

  1. 계층적 상태에 대한 지원이 없습니다.
  2. 유니티의 애니메이션 이벤트에 대한 지원이 없습니다.
  3. 모션이 없는 상태에 대한 지원이 없습니다(애니메이션 클립 집합 없음).
  4. 계층 메뉴에 대한 지원이 없으므로 아바타 마스크 사용, 블렌딩 등과 같이 둘 이상의 계층 간에 애니메이션을 혼합할 수 없습니다.
  5. Blend 트리를 사용할 때, 1D와 2D 블렌드 트리에서 블렌딩 값을 [-1, 1] 사이의 값을 가지는 게 필수입니다.
Back to top