유니티 NetworkRunner에 대해서 #Fusion2

NetworkRunner란?

Network Runner는 네트워크 시스템의 중심이 되는 컴포넌트입니다. 

 

Network Runner는 다음과 같은 핵심 역할을 합니다.

  1. Network Peer 관리
  2. SimulationBehaviour/INetworkCallbacks을 관리
  3. Game Session / (Join/Create) Room 관리
  4. Tick 관리
  5. Player / PlayerRef 관리

Network Peer 관리

Network Runner는 각 Peer를 관리한다고 해서 Scene Hierachy에 각 클라이언트마다 생겨나지는 않습니다. 클라이언트는 자신의 인스턴스에서 Network Runner를 생성하기 때문에 Scene에는 본인 자신꺼 하나의 Network Runner만이 존재합니다. 

 

해당 Network Runner를 이용해서 서로 Client간에 연결되고 상호작용을 할 수 있습니다.

 


Network Runner 생성방식

  1. Runtime에 Prefab을 활용해서 생성하기
  2. Scene Object로 로드 되기(미리 배치해 두는 방식)
  3. 게임오브젝트에 Network Runner 컴포넌트를  Adding하면서 동적으로 생성하기

Game Session / (Join/Create) Room 관리

Network Runner 인스턴스는 생성된 이후에 MatchMaking 혹은 Create/Join Room을 통해 연결되어야 합니다.

연결을 시도할 때 "StartGame"함수를 사용하며, 'StartGameArgs'를 통해 Room에 관련된 값들을 조절하고 참여하는 Peer을 생성합니다.

using Fusion;
using Fusion.Sockets;
using System.Threading.Tasks;
using UnityEngine;

public class NetworkManager : MonoBehaviour
{
    public NetworkRunner networkRunnerPrefab;
    private NetworkRunner runner;

    private async void Start()
    {
        // Network Runner 인스턴스 생성
        runner = Instantiate(networkRunnerPrefab);
        
        // StartGameArgs 설정
        StartGameArgs startGameArgs = new StartGameArgs()
        {
            GameMode = GameMode.AutoHostOrClient,  // 방이 없으면 호스트로 방을 생성하고, 있으면 클라이언트로 참여
            SessionName = "RoomName",              // Room 이름
            Scene = SceneManager.GetActiveScene().buildIndex,  // 현재 씬의 인덱스를 사용하여 씬 로딩
            SceneManager = gameObject.AddComponent<NetworkSceneManagerDefault>()  // 씬 관리 매니저 설정
        };

        // StartGame 함수로 Room 연결
        var result = await runner.StartGame(startGameArgs);

        if (result.Ok)
        {
            Debug.Log("Room에 성공적으로 연결되었습니다.");
        }
        else
        {
            Debug.LogError($"Room에 연결 실패: {result.ShutdownReason}");
        }
    }
}

 

Network Runner는 사용된 이후 재사용이 불가능해지기 때문에, Network Runner는 세션에 연결된 이후 연결이 해제되거나 실패가 된다면 Network Runner는 파괴해야 합니다. 반드시요.


Game Session / (Join/Create) Room 관리

Network Runner가 Game Session을 실행시킨 이후에는 자동으로 모든 "SimulationBehaviour"컴포넌트와 "INetworkRunnerCallbacks"인터페이스를 구현하는 컴포넌트들을 찾아 등록합니다.

 

OnPlayerJoined콜백함수와 OnPlayerLeft콜백함수, OnShutdown콜백함수등과 같이 콜백 함수를 받고 싶으면 INetworkRunnerCallbacks 인터페이스를 구현하면 되고, 자동으로 Network Runner가 상황에 맞는 함수를 Call해줍니다.

 

즉, Custom Runner를 만들고 싶다면, Network Runner의 특정 기능을 만들고 싶을 때는 "SimulationBehaviour"컴포넌트와 "INetworkRunnerCallbacks"인터페이스를 상속받는 컴포넌트를 제작하면 됩니다.

 


Tick 관리

Network Runner는 틱(Tick)이 언제 시뮬레이션되어야 하는지를 결정합니다. Tick을 관리하는 Tick Manangement로 활동하며, Tick이 시뮬레이션될 때마다 FixedUpdateNetwork 함수가 호출됩니다.

 

Tick을 쉽게 이해하는 것은 유니티 함수의 FixedUpdate의 Fixed TimeStep의 개념이라고 생각하시면 됩니다.

Fixed TimeStep

Tick은 Network 환경에서 1초에 얼마나 몇 번 시뮬레이션될 것인지 보장해 주기 위함입니다.

예를 들어 Tick이 30번이라면 네트워크 환경에서 1초 동안 30번 시뮬레이션된다는 것을 의미하며 이 수치가 클수록 성능을 최적화를 잘해주어야 Tick이 제대로 동작할 것입니다.


Player/PlayerRef 관

PlayerRef는 Player(Peer)를 나타내는 구조체입니다.

Network Peer가 Human Player를 나타내는 경우, PlayerRef는 해당 Peer를 식별하는 데 사용됩니다.

PlayerRef는 해당 Peer를 식별하는데 사용

 

    public void OnPlayerJoined(NetworkRunner runner, PlayerRef playerRef)
    {
        Debug.Log($"Player joined with PlayerRef ID: {playerRef.PlayerId}");

        // 새로운 플레이어에 대한 네트워크 객체 생성
        runner.Spawn(playerPrefab, Vector3.zero, Quaternion.identity, playerRef);
    }

    public void OnPlayerLeft(NetworkRunner runner, PlayerRef playerRef)
    {
        Debug.Log($"Player left with PlayerRef ID: {playerRef.PlayerId}");

        // PlayerRef와 연관된 모든 네트워크 객체 삭제
        runner.Despawn(playerRef);
    }