애니메이션
개요
Fusion 애니메이션 샘플은 Fusion을 사용하여 애니메이션 네트워킹을 처리하는 6가지 접근 방식을 보여줍니다.
예제 1부터 5는 렌더링 정확 접근법을 사용합니다. 반면 예 6은 틱 정확한 접근 방식을 나타냅니다. 각 예는 대략 1초 간격으로 다리 및 팔 히트 박스를 그리면서 서버 캐릭터와 프록시 캐릭터 사이의 결과 정밀도를 보여줍니다. 애니메이션 정밀도는 게임이 지연 보상을 사용할 때 특히 중요합니다.
다운로드
버전 | 릴리즈 일자 | 다운로드 | |
---|---|---|---|
2.0.10 | Dec 19, 2024 | Fusion Animations 2.0.10 Build 742 |
폴더 구조
프로젝트는 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개 버튼). 이를 통해 편집기에서 상태 권한, 입력 권한 및 프록시 결과를 보고 비교할 수 있습니다.
컨트롤
모든 예는 3개의 애니메이션 상태만 사용합니다. 유휴 애니메이션은 기본적으로 플레이되며 위 화살표 키를 누르면 캐릭터 실행 애니메이션이 시작되고 스페이스 키를 누르면 점프 애니메이션이 트리거 됩니다.
여러 피어로 플레이하는 동안 숫자 패드 0, 1, 2 및 3 키를 사용하여 피어 간을 전환할 수 있습니다. 또는 러너 가시성 제어 창에서 피어를 전환할 수 있습니다(상위 메뉴 Fusion > Windows > Runner Visibility Controls).
애니메이션 예측 이해하기
정확한 지연 보상과 같은 특정 게임 애플리케이션에서는 피어 간의 정확한 애니메이션 동기화가 중요할 수 있습니다. 애니메이션이 완벽하게 동기화되면 한 클라이언트에서 인식된 히트도 서버에서 인식되어 좋은 플레이어 경험을 얻을 수 있습니다. 물론 캐릭터 히트 박스가 애니메이션의 영향을 받는 경우에만 적용됩니다. 중요한 개념에 대해 자세히 설명하는 Fusion 매뉴얼의 애니메이션페이지를 확인하십시오.
모든 예는 로컬 플레이어가 볼 수 있는 다리 및 팔 히트 박스의 예상 위치(프록시의 히트 박스* 캐릭터 히트 박스는 파란색으로 표시됨)와 서버에 표시되는 위치(녹색)를 보여줍니다. 애니메이션 정밀도가 높을수록 상자가 더 가깝게 정렬됩니다.
히트 박스 그리기는 플레이어 프리팹 위에 놓인 HitboxDraw
스크립트로 진행됩니다. 차이를 더 잘 비교하기 위해 50틱 간격(약 1초)으로 히트 박스를 그립니다.
프록시 객체 = 입력 권한(로컬 플레이어가 제어하지 않음) 또는 상태 권한(인스턴스가 해당 네트워크 상태, 일반적으로 서버의 인스턴스에 대한 권한을 갖지 않음)가 없는 네트워크 객체 인스턴스입니다. 간단히 말하면 클라이언트로 플레이할 때 프록시 캐릭터는 플레이어가 볼 수 있는 다른 플레이어입니다.
네트워크 조건 시뮬레이션
애니메이션 정밀도 향상을 위한 일부 변경 사항(예: 보간 데이터 사용)은 나쁜 네트워크 조건에서 더 잘 관찰됩니다. 이러한 조건을 신속하게 시뮬레이션하기 위해 다루기 힘든 도구를 사용할 수 있습니다. 시뮬레이션 네트워크 조건 섹션에서 자세히 확인하십시오.
예제 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);
}
예제 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);
}
보간 데이터와 최신 데이터의 사용량을 비교하려면 플레이어 컴포넌트에 간단한 확인란이 있습니다. 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);
}
예제 5 - 애니메이터를 사용한 네트워크 FSM
렌더링 정확 접근 방법
이 예제에서는 인기 있는 타사 애니메이션 에셋 Animancer와 이 샘플에서만 현재 미리 보기 중인 네트워크 FSM 애드온을 사용합니다. 첫 번째 예제와 유사한 방식으로 Animancer를 FSM 없이도 사용할 수 있습니다.
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(계층적 유한 상태 머신)을 효과적으로 만들 수 있습니다. 예를 들어, 하위 상태 머신은 애어본 상위 상태에서 제어되는 점프, 넘어짐 및 착지와 같은 상태를 가진 에어본 머신일 수 있습니다. 이러한 분리는 많은 상태의 복잡한 애니메이션 설정을 제어할 때 유용합니다.
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 애니메이션 컨트롤러는 유니티의 로우 레벨 Playables API 위에 직접 구축된 틱 정확 애니메이션 솔루션입니다.
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에서 사용되는 애니메이션 컨트롤러의 정제된 버전입니다.
타사 에셋
애니메이션 샘플에는 해당 제작자가 제공하는 여러 에셋이 포함되어 있습니다. 전체 패키지는 해당 사이트에서 자체 프로젝트를 위해 구입할 수 있습니다:
- Kybernetik의 Animancer LITE
중요: 상업적 프로젝트에 사용하려면 해당 제작자로부터 라이선스를 구입해야 합니다.
Back to top