카테고리 없음

유니티 포톤을 이용한 멀티플레이 구현

이황충 2024. 6. 24. 21:16

유니티 게임개발캠프 TIL 43일차

 

오늘도 포톤을 이용한 멀티플레이 구현을 했다.

여전히 수많은 오류들과 간단해 보이는 작업들에서 끝없이 막혀만갔다.

 

먼저 로비라는 개념과 방이라는 개념이 이미 포톤매니저에 있어서

내가 이 프로젝트에서 만든 로비와 개념이 섞이면서 많이 헷갈리게 됐다. 

 

Photon Unity Networking (PUN) 기초 설정 및 연결

주요 개념:

  • 서버 연결: PhotonNetwork.ConnectUsingSettings()를 사용하여 Photon 서버에 연결합니다. 이는 멀티플레이어 상호작용을 위한 기본 네트워킹 환경을 설정합니다.
    • 장점: 간단한 함수 호출로 서버에 쉽게 연결할 수 있으며, Photon의 강력한 서버 인프라를 활용할 수 있습니다.
    • 필수 사항: 앱 ID 및 설정 파일이 올바르게 구성되어 있는지 확인해야 합니다.
using Photon.Pun;

public class NetworkManager : MonoBehaviourPunCallbacks
{
    void Start()
    {
        PhotonNetwork.ConnectUsingSettings(); // 서버에 연결
    }

    public override void OnConnectedToMaster()
    {
        PhotonNetwork.JoinLobby(); // 마스터 서버에 연결되면 로비에 접속
    }
}

 

로비 접속: PhotonNetwork.JoinLobby()를 사용하여 로비에 접속합니다. 로비는 플레이어들이 게임 시작 전에 대기할 수 있는 공간입니다.

  • 장점: 로비에서 다른 플레이어와의 매칭이 이루어지므로, 게임 시작 전 대기 상태를 관리할 수 있습니다.
  • 필수 사항: 서버에 연결된 후 로비에 접속하는 로직이 필요합니다.
public override void OnConnectedToMaster()
{
    PhotonNetwork.JoinLobby(); // 로비에 접속
}

 

방 생성 및 참가: PhotonNetwork.CreateRoom()와 PhotonNetwork.JoinRandomRoom()를 사용하여 방을 생성하거나 참가합니다.

  • 장점: 방을 생성하여 프라이빗 게임을 설정하거나, 랜덤으로 방에 참가하여 빠른 매칭을 할 수 있습니다.
  • 필수 사항: 방 설정과 참가 로직을 구분하여 구현해야 합니다.
public void CreateRoom()
{
    PhotonNetwork.CreateRoom("RoomName"); // 방 생성
}

public void JoinRandomRoom()
{
    PhotonNetwork.JoinRandomRoom(); // 랜덤 방 참가
}

 

멀티플레이어 환경에서의 플레이어 생성 및 관리

주요 포인트:

  • 플레이어 생성: PhotonNetwork.Instantiate()를 사용하여 네트워크 상의 플레이어 객체를 생성합니다.
    • 장점: 모든 클라이언트에 동일한 플레이어 객체가 생성되어 동기화가 쉽습니다.
    • 필수 사항: 네트워크 객체를 위한 프리팹을 준비해야 합니다.
void Start()
{
    if (PhotonNetwork.IsConnectedAndReady)
    {
        PhotonNetwork.Instantiate("PlayerPrefab", Vector3.zero, Quaternion.identity); // 플레이어 생성
    }
}

 

플레이어 구분: 로컬 플레이어와 네트워크 플레이어를 구분하여 처리합니다.

  • 장점: 로컬 플레이어의 입력과 네트워크 플레이어의 동작을 구분하여 처리할 수 있습니다.
  • 필수 사항: PhotonView 컴포넌트를 사용하여 로컬 플레이어를 식별합니다.
if (photonView.IsMine)
{
    // 로컬 플레이어 처리
}
else
{
    // 네트워크 플레이어 처리
}

 

씬 전환 시 객체 유지: DontDestroyOnLoad를 사용하여 씬이 전환될 때 플레이어 객체가 파괴되지 않도록 합니다.

  • 장점: 플레이어 상태와 데이터를 유지할 수 있습니다.
  • 필수 사항: 씬 전환 시 객체가 유지되도록 설정해야 합니다.
void Awake()
{
    DontDestroyOnLoad(this.gameObject); // 객체 유지
}

싱글플레이와 멀티플레이의 차이점 처리

주요 인사이트:

  • 게임 시작 처리: 싱글플레이와 멀티플레이의 게임 시작 로직을 다르게 관리합니다.
    • 장점: 각각의 모드에 맞는 최적화된 게임 시작 방식 제공.
    • 필수 사항: 모드에 따라 다른 게임 시작 로직을 구현합니다.
void StartGame()
{
    if (isMultiplayer)
    {
        PhotonNetwork.LoadLevel("MultiplayerScene"); // 멀티플레이어 씬 로드
    }
    else
    {
        LoadSinglePlayerGame(); // 싱글플레이어 게임 시작
    }
}

 

로컬 플레이어 생성: PhotonNetwork를 사용하지 않는 로컬 플레이어 객체를 생성합니다.

  • 장점: 네트워크 연결이 필요 없는 싱글플레이어 모드를 지원합니다.
  • 필수 사항: 로컬 플레이어를 위한 별도의 생성 로직이 필요합니다.
void StartSinglePlayer()
{
    Instantiate(singlePlayerPrefab, Vector3.zero, Quaternion.identity); // 로컬 플레이어 생성
}

 

자동 씬 동기화: PhotonNetwork.AutomaticallySyncScene 설정을 통해 모든 플레이어가 동일한 씬으로 자동으로 이동하도록 합니다.

  • 장점: 씬 전환이 자동으로 동기화되어 플레이어 간의 일관성을 유지할 수 있습니다.
  • 필수 사항: 자동 씬 동기화를 설정합니다.
void Awake()
{
    PhotonNetwork.AutomaticallySyncScene = true; // 자동 씬 동기화 설정
}

PhotonNetwork.LoadLevel() 사용 시의 주의점

주요 포인트:

  • 씬 전환 시 플레이어 객체 재생성: PhotonNetwork.LoadLevel()을 사용할 때 모든 플레이어 객체가 올바르게 재생성되도록 합니다.
    • 장점: 씬 전환 후에도 모든 플레이어가 동일한 환경을 유지합니다.
    • 필수 사항: OnJoinedRoom()에서 객체를 재생성합니다.
public override void OnJoinedRoom()
{
    PhotonNetwork.Instantiate("PlayerPrefab", Vector3.zero, Quaternion.identity); // 플레이어 재생성
}

 

동일한 씬으로 이동: LoadLevel()을 사용하여 모든 플레이어가 동일한 씬으로 이동하도록 합니다.

  • 장점: 모든 플레이어가 같은 씬에서 게임을 진행할 수 있습니다.
  • 필수 사항: 씬 로드를 동기화합니다.
public void LoadGameScene()
{
    PhotonNetwork.LoadLevel("GameScene"); // 동일 씬으로 이동
}

 

OnJoinedRoom()에서 재설정: OnJoinedRoom()에서 네트워크 플레이어를 재생성하고, 카메라 타겟을 설정합니다.

  • 장점: 씬 전환 후 플레이어와 카메라 설정이 일관되게 유지됩니다.
  • 필수 사항: 씬 전환 후 객체와 카메라를 재설정합니다.
public override void OnJoinedRoom()
{
    GameObject player = PhotonNetwork.Instantiate("PlayerPrefab", Vector3.zero, Quaternion.identity); // 플레이어 재생성
    Camera.main.GetComponent<CameraFollow>().SetTarget(player.transform); // 카메라 타겟 설정
}

 

PhotonNetwork와 관련된 객체 정리

주요 포인트:

  • 객체 정리: OnDestroy()에서 PhotonNetwork.Destroy()를 사용하여 객체를 정리합니다.
    • 장점: 메모리 누수를 방지하고 자원을 효율적으로 관리할 수 있습니다.
    • 필수 사항: 객체가 파괴될 때 정리 로직을 추가합니다.
void OnDestroy()
{
    if (PhotonNetwork.IsConnected)
    {
        PhotonNetwork.Destroy(this.gameObject); // 객체 정리
    }
}

 

씬 전환 및 게임 종료 시: PhotonNetwork.DestroyAll()을 사용하여 모든 객체를 정리합니다.

  • 장점: 씬 전환이나 게임 종료 시 불필요한 객체가 남지 않도록 합니다.
  • 필수 사항: 씬 전환 또는 게임 종료 시 정리 로직을 추가합니다.
public void OnGameEnd()
{
    PhotonNetwork.DestroyAll(); // 모든 객체 정리
}