This document is about: FUSION 2
SWITCH TO

애니메이션

Level 4

개요

Fusion 애니메이션 샘플은 Fusion을 사용하여 애니메이션 네트워킹을 처리하는 6가지 접근 방식을 보여줍니다.

개요
Fusion의 애니메이션 소개 및 렌더 정확한 애니메이션과 틱 정확한 애니메이션의 차이점은 Fusion 매뉴얼의 애니메이션 문서 페이지를 참고하세요.

예제 1부터 5는 렌더링 정확 접근법을 사용합니다. 반면 예 6은 틱 정확한 접근 방식을 나타냅니다. 각 예는 대략 1초 간격으로 다리 및 팔 히트 박스를 그리면서 서버 캐릭터와 프록시 캐릭터 사이의 결과 정밀도를 보여줍니다. 애니메이션 정밀도는 게임이 지연 보상을 사용할 때 특히 중요합니다.

Hitboxes

다운로드

버전 릴리즈 일자 다운로드
2.0.9 Aug 27, 2024 Fusion Animations 2.0.9 Build 638

폴더 구조

프로젝트는 6개의 작은 독립적인 예제로 구성되어 있습니다.

/01_AnimatorSimple 예제 1 - 애니메이터를 사용한 네트워크화된 상태
/02_AnimatorInterpolated 예제 2 - 애니메이터를 사용한 보간 네트워크 상태
/03_AnimatorStateSync 예제 3 - 애니메이터를 사용한 상태 동기화
/04_NetworkMecanimAnimator 예제 4 - 네트워크 메카님 애니메이터
/05_AnimancerFSM 예제 5 - 애니메이터를 사용한 네트워크 FSM
/06_FusionAnimationController 예제 6 - Fusion 애니메이션 컨트롤러
/Common 모든 예에서 공통적으로 사용되는 프리팹, 스크립트 및 자료
/ThirdParty 타사 에셋 (모델, 애니메이션, 애니멘서 라이트)

방법

게임 시작하기

각 예제에는 열고 플레이할 수 있는 고유한 씬 파일이 있습니다. 또는 모든 예제는 시작 씬(/Common/Start)에서 시작할 수 있습니다.

시연을 위해 호스트 + 클라이언트 2개가 있는 멀티-피어 모드를 권장합니다(시작 호스트 + 클라이언트 2개 버튼). 이를 통해 편집기에서 상태 권한, 입력 권한 및 프록시 결과를 보고 비교할 수 있습니다.

Start

컨트롤

모든 예는 3개의 애니메이션 상태만 사용합니다. 유휴 애니메이션은 기본적으로 플레이되며 위 화살표 키를 누르면 캐릭터 실행 애니메이션이 시작되고 스페이스 키를 누르면 점프 애니메이션이 트리거 됩니다.

여러 피어로 플레이하는 동안 숫자 패드 0, 1, 23 키를 사용하여 피어 간을 전환할 수 있습니다. 또는 러너 가시성 제어 창에서 피어를 전환할 수 있습니다(상위 메뉴 Fusion > Windows > Runner Visibility Controls).

애니메이션 예측 이해하기

정확한 지연 보상과 같은 특정 게임 애플리케이션에서는 피어 간의 정확한 애니메이션 동기화가 중요할 수 있습니다. 애니메이션이 완벽하게 동기화되면 한 클라이언트에서 인식된 히트도 서버에서 인식되어 좋은 플레이어 경험을 얻을 수 있습니다. 물론 캐릭터 히트 박스가 애니메이션의 영향을 받는 경우에만 적용됩니다. 중요한 개념에 대해 자세히 설명하는 Fusion 매뉴얼의 애니메이션페이지를 확인하십시오.

모든 예는 로컬 플레이어가 볼 수 있는 다리 및 팔 히트 박스의 예상 위치(프록시의 히트 박스* 캐릭터 히트 박스는 파란색으로 표시됨)와 서버에 표시되는 위치(녹색)를 보여줍니다. 애니메이션 정밀도가 높을수록 상자가 더 가깝게 정렬됩니다.

히트 박스
노트: 틱 정확한 솔루션을 사용하면 완벽하고 가장 신뢰할 수 있는 애니메이션 정밀도를 얻을 수 있지만(예 6), 정확하게 설정하고 유지하는 것이 가장 복잡하다는 큰 단점이 있습니다. 이 길을 가기 전에 렌더링 및 틱 정확 애니메이션 솔루션의 차이점을 이해해야 합니다.

히트 박스 그리기는 플레이어 프리팹 위에 놓인 HitboxDraw 스크립트로 진행됩니다. 차이를 더 잘 비교하기 위해 50틱 간격(약 1초)으로 히트 박스를 그립니다.

HitboxDraw

프록시 객체 = 입력 권한(로컬 플레이어가 제어하지 않음) 또는 상태 권한(인스턴스가 해당 네트워크 상태, 일반적으로 서버의 인스턴스에 대한 권한을 갖지 않음)가 없는 네트워크 객체 인스턴스입니다. 간단히 말하면 클라이언트로 플레이할 때 프록시 캐릭터는 플레이어가 볼 수 있는 다른 플레이어입니다.

네트워크 조건 시뮬레이션

애니메이션 정밀도 향상을 위한 일부 변경 사항(예: 보간 데이터 사용)은 나쁜 네트워크 조건에서 더 잘 관찰됩니다. 이러한 조건을 신속하게 시뮬레이션하기 위해 다루기 힘든 도구를 사용할 수 있습니다. 시뮬레이션 네트워크 조건 섹션에서 자세히 확인하십시오.

Clumsy

예제 1 - 애니메이터를 사용한 네트워크화된 상태

렌더링 정확 접근 방식

이 예제에서는 최신 네트워크 상태를 사용하여 애니메이터 매개 변수를 제어하는 가장 간단한 솔루션을 보여 줍니다.

일반적으로 기존 네트워크 상태(예를 들어_controller.Speed)를 사용하여 애니메이션을 제어할 수 있습니다. 정확한 애니메이션은 Render 또는 OnChanged 콜백 메소드에서 네트워크 데이터를 기반으로 설정됩니다.

C#

private CharacterController _controller;
private Animator _animator;

public override void Render()
{
    if (_lastVisibleJump < _controller.JumpCount)
    {
        _animator.SetTrigger("Jump");
    }

    _lastVisibleJump = _controller.JumpCount;

    _animator.SetFloat("Speed", _controller.Speed);
}
예제
노트: 이동 애니메이션이 두 개의 다른 클라이언트가 참여한 후 시작할 때 동기화가 매우 해제될 수 있는 방법에 주목하십시오. 이는 애니메이션 시간이 동기화되지 않으므로 상태 권한의 캐릭터가 이미 몇 초 동안 애니메이션을 플레이하고 있음에도 불구하고 모든 클라이언트에서 애니메이션이 0부터 플레이되기 시작하기 때문입니다. 이는 다음 애니메이션 액션(예: 점프)으로 자동으로 수정되지만 이러한 동작을 허용할 수 없는 경우 애니메이션 시간의 동기화가 필요합니다. 예제 3을 참조하십시오.

예제 2 - 애니메이터를 사용한 보간 네트워크 상태

렌더링 정확 접근 방식

이 예제는 최근의 것이 아니라 보간 된 네트워크 데이터를 사용하여 이전의 예에서 한 단계 더 발전한 것입니다. 네트워크 조건이 이상적이지 않을 때도 보간 된 데이터를 사용하면 애니메이션이 더 정밀해지고 이 정밀도가 유지됩니다(네트워크 조건 시뮬레이션#simulating_network_conditions)섹션을 참조하세요).

C#

private CharacterController _controller;
private Animator _animator;

public override void Render()
{
    int jumpCount = _useInterpolation == true ? _controller.InterpolatedJumpCount : _controller.JumpCount;

    if (_lastVisibleJump < jumpCount)
    {
        _animator.SetTrigger("Jump");
    }

    _lastVisibleJump = jumpCount;

    float speed = _useInterpolation == true ? _controller.InterpolatedSpeed : _controller.Speed;
    _animator.SetFloat("Speed", speed);
}
예제
많은 프로젝트에서 보간기를 사용하는 것은 불필요한 복잡성이 될 수 있으며 예제 1의 솔루션은 충분한 결과를 얻을 수 있으므로 게임이 향상된 정밀도를 통해 이점을 얻을 수 있는지 확인하십시오.

보간 데이터와 최신 데이터의 사용량을 비교하려면 플레이어 컴포넌트에 간단한 확인란이 있습니다. Player_AnimatorInterpolated 프리팹을 찾아서 Use Interpolation을 끕니다. 추가 클라이언트 2개로 게임을 시작하고 불량 네트워크를 시뮬레이션하고 20%를 떨어뜨립니다.

예제 3 - 애니메이터를 사용한 상태 동기화

렌더링 정확 접근 방식

이 예제에서는 플레이어의 현재 애니메이터 상태와 시간을 주기적으로 동기화하는 특수 컴포넌트인 AnimatorStateSync를 추가합니다. 상태 동기화는 플레이어가 게임에 참여한 후 또는 프록시 개체가 관심 영역에 진입한 후에도 프록시 애니메이션이 동기화되도록 보장합니다.

예제

상태 동기화는 더 오래 실행되는 애니메이션(예: 로코모션) 또는 렌더링 정확한 접근 방식으로 발생할 수 있는 실수를 수정하는 데 특히 중요할 수 있습니다.

예제: 로컬 플레이어가 게임에 참여할 때, 원격 플레이어는 이미 10초 동안 실행 중인 애니메이션을 수행하고 있습니다. 그러나 애니메이션 시간이 동기화되지 않을 때, 로컬 플레이어 머신의 프록시 캐릭터는 처음부터 실행 중인 애니메이션을 시작하여 다른 애니메이션 타이밍을 만듭니다. 타이밍은 다음 애니메이션 액션(예: 점프)으로 자체적으로 수정되지만, 그때까지 애니메이션은 동기화되지 않습니다.

예제 4 - 네트워크 메카님 애니메이터

렌더링 정확 접근 방식

애니메이션 동기화를 위한 간단한 솔루션은 Fusion SDK와 함께 제공되는 NetworkMecanimAnimator (NMA) 컴포넌트입니다.

네트워크 메카님 애니메이터는 보간 된 네트워크 데이터를 사용하지 않기 때문에 애니메이션 정밀도가 예제 3의 솔루션에서 가능한 것보다 낮습니다. NMA는 기존 네트워크 데이터를 사용하지 않고 현재 Animator 파라미터를 자체 네트워크 데이터 구조체로 복사하므로 특히 동기화된 파라미터가 많이 변경되는 경우 대역폭 집약적입니다.

네트워크 메카님 애니메이터에 대한 자세한 내용은 애니메이션 문서를 확인하십시오.

C#

private CharacterController _controller;
private NetworkMecanimAnimator _networkAnimator;

public override void FixedUpdateNetwork()
{
    if (IsProxy == true)
        return;

    if (Runner.IsForward == false)
        return;

    if (_controller.HasJumped == true)
    {
        _networkAnimator.SetTrigger("Jump", true);
    }

    _networkAnimator.Animator.SetFloat("Speed", _controller.Speed);
}
Example

예제 5 - 애니메이터를 사용한 네트워크 FSM

렌더링 정확 접근 방법

이 예제에서는 인기 있는 타사 애니메이션 에셋 Animancer와 이 샘플에서만 현재 미리 보기 중인 네트워크 FSM 애드온을 사용합니다. 첫 번째 예제와 유사한 방식으로 Animancer를 FSM 없이도 사용할 수 있습니다.

면책 사항: Animancer는 Kybernetik이 개발, 유지 및 지원하는 제3자 유니티 에셋입니다. 작성 당시 Fusion과 함께 사용할 수 있습니다. Photon은 즉시 사용 가능한 Animancer-Fusion 통합을 제공하지 않습니다.
예제

Network FSM은 StateMachineController 컴포넌트를 게임 객체에 배치하고 StateMachineController 인터페이스를 구현하는 사용자 스크립트(예: 플레이어)를 필요로 합니다. StateMachineController는 필요한 데이터를 모든 피어에 자동으로 동기화하고 등록된 시스템을 업데이트합니다.

C#

public class Player : NetworkBehaviour, IStateMachineOwner
{
    private PlayerBehaviourMachine _fullBodyMachine;

    void IStateMachineOwner.CollectStateMachines(List<IStateMachine> stateMachines)
    {
        var states = GetComponentsInChildren<PlayerStateBehaviour>();
        var animancer = GetComponentInChildren<AnimancerComponent>();

        _fullBodyMachine = new PlayerBehaviourMachine("Full Body", _controller, animancer, states);
        stateMachines.Add(_fullBodyMachine);
    }
}

애니메이션은 상태 변화에 따라 플레이됩니다. 상태는 StateBehaviour 스크립트가 연결된 플레이어 계층 내 객체인 단일 플레이어의 동작(예: 점프 상태, 이동 상태) 또는 State 스크립트를 상속하는 일반 클래스(예: 이 예에서는 설명하지 않음)를 나타냅니다.

C#

public override void FixedUpdateNetwork()
{
    if (IsProxy == true)
        return;

    if (_controller.HasJumped == true)
    {
        _fullBodyMachine.TryActivateState<PlayerJumpState>();
    }
}

C#

public class PlayerJumpState : PlayerStateBehaviour
{
    [SerializeField]
    private ClipTransition _jumpClip;

    protected override void OnEnterStateRender()
    {
        Animancer.Play(_jumpClip);
    }

    protected override void OnFixedUpdate()
    {
        if (Machine.StateTime >= _jumpClip.Length * _jumpClip.Speed)
        {
            // Jump animation should be finished, let's leave this state
            Machine.TryDeactivateState(StateId);
        }
    }
}

상위 상태에서 제어되는 하위 상태 머신(하위 상태 머신)를 생성하여 HFSM(계층적 유한 상태 머신)을 효과적으로 만들 수 있습니다. 예를 들어, 하위 상태 머신은 애어본 상위 상태에서 제어되는 점프, 넘어짐착지와 같은 상태를 가진 에어본 머신일 수 있습니다. 이러한 분리는 많은 상태의 복잡한 애니메이션 설정을 제어할 때 유용합니다.

노트: 이 예제에는 자식 시스템이 표시되지 않지만 기본적으로 원하는 부모 상태의 OnCollectChildStateMachines 메소드에서 자식 시스템을 제공한 다음 평소와 같이 상태 시스템을 제어하기에 충분합니다.

Network FSM은 기본적으로 보간 된 데이터를 기반으로 프록시 상태를 전환하고 렌더 호출에서 확인할 때도 보간 되는 현재 상태 시간(Machine.StateTime)을 제공합니다. 이를 통해 많은 노력 없이도 정밀한 애니메이션 정밀도를 확보할 수 있습니다.

C#

public class PlayerLocomotionState : PlayerStateBehaviour
{
    [SerializeField]
    private LinearMixerTransition _moveMixer;

    protected override void OnEnterStateRender()
    {
        Animancer.Play(_moveMixer);

        // Update the animation time based on the state time
        _moveMixer.State.Time = Machine.StateTime;
    }

    protected override void OnRender()
    {
        _moveMixer.State.Parameter = Controller.InterpolatedSpeed;
    }
}

예제 6 - Fusion 애니메이션 컨트롤러

틱 정확 접근 방법

Fusion 애니메이션 컨트롤러는 실험 상태이고 웹 문서화가 부족합니다. 이해를 위해서는 중간 레벨의 코딩 기술이 필요합니다.

Fusion 애니메이션 컨트롤러는 유니티의 로우 레벨 Playables API 위에 직접 구축된 틱 정확 애니메이션 솔루션입니다.

게임에서 사용하기 전에 맞춤형 애니메이션 솔루션의 한계를 이해했는지 확인하십시오. 틱 정확한 애니메이션에 대한 자세한 내용은 애니메이션문서에서 확인하십시오.
Example

Fusion 애니메이션 컨트롤러는 메카님과 마찬가지로 애니메이션 레이어로 작동합니다. 모든 레이어에는 하나 이상의 애니메이션 상태가 포함됩니다. 레이어와 상태는 모두 객체 계층 구조의 객체로 간단히 표현됩니다(Player_FusionAnimationController 프리팹 참조). 애니메이션은 AnimationController 컴포넌트를 통해 코드에서 제어됩니다.

C#

private CharacterController _controller;
private PlayerLocomotionState _locomotionState;
private PlayerJumpState _jumpState;

public override void FixedUpdateNetwork()
{
    if (IsProxy == true)
        return;

    if (_controller.HasJumped == true)
    {
        _jumpState.Activate(0.15f);
    }
    else if (_jumpState.IsPlaying() == false || _jumpState.IsFinished(-0.15f, false) == true)
    {
        _locomotionState.Activate(0.15f);
    }
}

Fusion 애니메이션 컨트롤러는 BR200에서 사용되는 애니메이션 컨트롤러의 정제된 버전입니다.

타사 에셋

애니메이션 샘플에는 해당 제작자가 제공하는 여러 에셋이 포함되어 있습니다. 전체 패키지는 해당 사이트에서 자체 프로젝트를 위해 구입할 수 있습니다:

중요: 상업적 프로젝트에 사용하려면 해당 제작자로부터 라이선스를 구입해야 합니다.

Back to top