수정중인 페이지 입니다.

빠르게 시작 하기

빠르게 시작 하기

새 유니티 프로젝트를 만들고 Fusion SDK를 가져온 다음 멀티플레이어 게임을 시작하려고 합니다. 또는 기존의 단일 플레이어 프로토타입이 있을 수도 있습니다. 두 가지 경우 어디서부터 시작할까요?

샘플에서 시작하는 것이 좋습니다. 샘플들은 멀티플레이어 게임을 위한 모범 사례와 디자인 패턴을 간단하게 구현하는 예제를 제공하며, 이들 중 다수는 직접 작성하는 프로젝트에 복사하여 사용할 수 있습니다.

그러나 코딩을 시작하기 전에 이 문서에서는 가장 중요한 컴포넌트를 설명하고 해당 컴포넌트가 무엇을 하는지를 설명하므로 실제 샘플 코드에서 무엇을 찾아야 하는지 알 수 있습니다.

메인 화면으로

기본 내용

두 개의 주요 Fusion 컴포넌트는 NetworkRunnerNetworkObject입니다. NetworkRunner는 Fusion의 핵심이라고 생각할 수 있습니다. 이 중 하나만 씬에 있고 네트워킹과 시뮬레이션을 모두 관리할 것입니다. 이것은 서버와 클라이언트 모두에서 발생합니다.

NetworkObject를 일반 유니티 프리팹 또는 씬 개체에 추가하면 런타임에 네트워크 ID가 할당되고 동기화된 틱 기반 시뮬레이션의 일부가 됩니다. 또한 특정 객체를 항상 데이터 전송의 일부로 만드는 등 몇 가지 옵션(예: 전역 개체)을 구성할 수 있습니다.

다른 두 가지 기본 behaviour들은 SimulationBehaviourNetworkBehaviour에서 상속받고 게임 오브젝트에 실제 네트워킹을 추가합니다.

(게임 상태를 구성하는) 네트워크 속성은 NetworkBehaviour(SimulationBehaviour의 특수 하위 클래스)에 추가되어야 하며, 후자는 네트워크 속성을 가지고 있지 않고 시뮬레이션 단계와 콜백을 제어하는 데 사용될 수 있습니다.

NetworkBehaviour는 네트워크에서 자동으로 동기화된 데이터를 보관하는 데 사용해야 합니다. 네트워크 상태 값을 정의하려면 다음과 같이 속성을 생성하여 [Networked]로 표시하면 됩니다:

[Networked] public byte life { get; set; }

[Networked]는 모든 원시 유형에서 작동합니다(단, bool은 단일 비트로 올바르게 직렬화되므로 NetworkBool을 대신 사용해야 합니다). 또한 모든 클라이언트에서 네트워크를 안전하게 식별할 수 있기 때문에 다른 NetworkObject(프리팹까지도)의 구조체 및 참조에도 동작합니다.

중요: Fusion은 빈 get/set 스텁을 실제 네트워크 상태 데이터에 액세스하는 코드로 대체하므로 이러한 스텁은 빈 상태이어야 합니다.

또한 네트워크 속성 값이 변경될 때마다 콜백이 트리거 되도록 쉽게 등록할 수 있습니다:

[Networked(OnChanged = "OnTypeChanged")] public Type type { get; set; }

public static void OnTypeChanged(Changed<TheClassWhichHasTheProperty> changed)
{
  // your code here - check API docs for more details
}

실제 콜백 이름 외에도 콜백이 실행되는 위치를 제어할 수 있습니다:

  • OnChangedLocal (true/false) - true로 설정하면 속성을 변경한 시스템에서 이벤트 후크가 호출됩니다(예: 서버(기본값 false).
  • OnChangedRemote (true/false) - 속성을 변경한 시스템에서만 이벤트 후크가 호출되도록 하려면 false로 설정합니다(기본값 true).

메인 화면으로

내장 네트워크 Behaviours

Fusion은 게임을 시작하거나 프로토타입으로 빠르게 구동할 수 있도록 다양한 사전 구축된 NetworkBehaviour를 제공합니다.

NetworkTransform은 개체 변환을 동기화된 상태로 유지합니다(콜라이더도 포함할 수 있음). 렌더링은 최신 스냅샷 보간법으로 자동으로 매우 부드럽게 유지합니다. 유니티의 Transform에 대한 데이터를 직접 변경함으로써 (어떤 게임 클라이언트에서도) 완전한 클라이언트 측 예측을 수행하는 것도 간단합니다.

물리학으로 제어되는 강체의 경우 NetworkRigidbody 가 권장됩니다. 동일한 보간 옵션이 작동하며 Fusion은 구성 옵션 설정만으로 PhysX에서 직접 전체 예측/롤백을 수행할 수 있습니다.

휴머노이드 캐릭터처럼 플레이어가 직접 제어하는 객체의 경우 NetworkCharacterController가 내장되어 있습니다. 보다 복잡한 사용 사례의 경우 표면 접선, 침투 보정 등을 제공하는 기본 정적 쿼리를 재사용하고 스티어링/이동용 사용자 정의 코드와 매치시킬 수 있습니다.

메인 화면으로

틱 기반 콜백

게임 플레이 시뮬레이션 코드를 작성하기 위해서는 SimulationBehaviour의 라이프 사이클이 실행됩니다. Awake()Start() 등에서 유니티에서 구축된 기능을 계속 사용할 수 있지만 일반적으로 네트워크 안전 대응에 유의하는 것이 좋습니다:

Fusion에서 Start()에 상응하는 것은 Spawned()이며, 특정 시스템(서버 또는 클라이언트)에서 해당 객체가 처음으로 활성화될 때 트리거 됩니다. 객체가 살아 있는 동안 변경되지 않는 항목을 한 번 초기화할 때 Awake()을 사용합니다. GetComponent<>()에 대한 호출은 종종 이 범주에 속하지만 일반적으로 Start()을 사용할 때는 Spawned()를 사용합니다.

가장 중요한 Fusion 콜백은 FixedUpdateNetwork()입니다. FixedUpdateNetwork()는 Fusion이 다음 네트워크 상태에 대한 로직을 실행하고 조정 중에 다시 시뮬레이션하는 데 사용합니다.

API 설명서에 이러한 모든 콜백에 대한 자세한 설명이 있지만, 중요한 점은 렌더링 속도와 무관하게 고정된 간격으로 FixedUpdate()와 같이 FixedUpdateNetwork()가 호출된다는 것입니다. 또한 FixedUpdate()와는 다르게 서버에서 가져온 변경 사항들을 조정하기 위해 시뮬레이션을 수행할 때 동일한 상태/프레임/틱에 대해 여러 번 호출할 수 있습니다.

네트워크 속성의 경우 Fusion이 FixedUpdateNetwork()를 호출하기 전에 모든 네트워크 상태 속성을 암시적으로 재설정하므로 재시뮬레이션은 투명합니다.

예를 들어, 객체가 NetworkTransform 을 사용하거나 다른 내장 컴포넌트 중 하나를 사용하는 한 FixedUpdateNetwork() 내에서 이와 같은 것을 실행하는 것은 매우 안전합니다:

transform.position += transform.forward * Runner.DeltaTime;

네트워크 틱 속도에 따라 시뮬레이션을 유지하는 데 필요하기 때문에 Runner.DeltaTime의 사용한다는 것에 주목하세요.

Render()FixedUpdateNetwork() 에 대한 모든 호출 후 및 LateUpdate() 전에 실행되도록 보장합니다.

메인 화면으로

입력

Fusion은 입력 처리를 두 단계로 나눕니다.

  1. 로컬 하드웨어에서 입력을 수집하여 구조체에 배치합니다. 이 작업은 항상 클라이언트 및 호스트(전용 서버가 아님)에서만 수행되며, 새 틱 표시마다 한 번씩 수행됩니다. 이것은 서버로 전송되고, 클라이언트의 즉각적인 예측에도 로컬로 사용됩니다.
  2. FixedUpdateNetwork()에서 이 입력을 읽어 게임 상태를 변경할 수 있습니다(시뮬레이션 진행). 이 작업은 클라이언트(입력 권한이 있는 네트워크 객체)와 호스트/서버 모두에서 수행할 수 있습니다. 클라이언트에서는 조정 롤백에서 동일한 틱/프레임에 대해 여러 번 발생할 수 있습니다.

첫 번째 단계는 플레이어가 하는 일을 기록하여 나중에 사용할 수 있도록 저장하는 일반적인 유니티 입력 처리 메커니즘으로 생각할 수 있으며, 두 번째 단계는 네트워크 상태를 수정하기 위해 입력을 적용하기 위한 분리된 스크립트입니다.

첫 번째 단계는 Fusion이 OnGetInput()콜백에서 폴링하고 두 번째 단계는 일반적으로 메인 캐릭터의 SimulationBehaviour에서 FixedUpdateNetwork() 내에서 GetInput() 또는 TryGetInput()을 호출하여 처리합니다.

메인 화면으로

원격 프로시저 호출

입력 구조체와 [Networked] 속성을 사용하는 것이 네트워크 클라이언트 간의 게임 상태를 동기화하고 서버 권한을 유지하는 데 필요한 방법이기는 하지만 가장 실용적인 해결책이 아닐 때가 있습니다.

예를 들어 클라이언트는 특정 키를 사용하여 인벤토리의 잠긴 문을 여는 것과 같이 입력 권한이 없는 개체와 드물지만 복잡한 상호 작용을 수행하려고 합니다.

서버에 사용할 키와 문을 알려주는 입력 구조체에 일부 필드를 포함할 수 있지만, 이러한 접근 방식은 거의 사용되지 않는 입력 구조체에 많은 혼란을 야기합니다.

또 다른 고려 사항은 일반 Fusion 입력이 신뢰할 수 없다는 것입니다. 패킷이 손실될 수 있습니다. 캐릭터 이동과 같은 연속 입력 형식을 수행하는 경우에는 이러한 현상이 거의 발생하지 않지만, 일회성 작업을 수행하는 경우에는 서버에 도착하는지 확인해야 할 수 있습니다.

이러한 경우 Fusion은 RPC(원격 프로시저 호출)를 지원합니다.

Fusion은 간단하면서도 강력한 RPC 용 구문을 구현합니다. 모든 SimulationBehaviour에 RPC를 정의하려면 일반적인 C# 메소드로 리턴 타입을 void[Rpc] 속성으로 태그 하여 선언합니다. Fusion 객체(예,NetworkObject 또는 PlayerRef-네트워크 식별자를 가지고 있는 모든 것) 구조체와 참조 뿐만 아니라 모든 원시 파라미터(bool 제외, 위 참고)를 받을수 있습니다.

[Rpc] 속성을 사용하면 호출할 수 있는 위치와 실행 위치를 필터링할 수 있습니다:

[Rpc(RpcSources.InputAuthority, RpcTargets.StateAuthority)]
public void RPC_Configure(string name, Color color)
{
    playerName = name;
    playerColor = color;
}

또한 "RPC" 접두사의 사용에 유의하십시오. 이 표기법을 정확하게 사용할 필요는 없지만 메소드 이름을 "rpc"(대소문자를 구분하지 않음)로 사전 또는 사후 수정해야 합니다.

소스 및 대상 속성 외에도 [Rpc] 속성에는 다음과 같은 추가 옵션 파라미터가 있습니다:

  • Channel (신뢰할 수 있음/신뢰할 수 없음) - 전송 중에 RPC가 손실되는 것을 상관하지 않는 경우 신뢰할 수 없음으로 설정합니다(기본값: 신뢰할 수 있음).
  • InvokeLocal (true/false) - 로컬 클라이언트에서 RPC를 호출하지 않으려면 false로 설정합니다(기본값: true).
  • InvokeResim (true/false) - 재시뮬레이션 중에도 RPC를 호출하려면 true로 설정합니다(기본값: false).

RPC에 대한 마지막 주의 사항은 RPC에는 명시적 상태가 없다는 것입니다. "모든 클라이언트"로 전송하더라도 아직 온라인 상태가 아닌 클라이언트는 RPC를 수신하지 않으며, 실행했다가 다시 로그인하는 클라이언트는 이 상태를 잊어버릴 수 있습니다. 이러한 이유로 RPC의 상태가 실제로 일시적(예: 채팅 메시지)인지 아니면 상태의 효과가 [Networked] 속성에 간접적으로 기록되는지 항상 확인해야 합니다.

기술문서 TOP으로 돌아가기