본문 바로가기
Hello, World!/Unity

좀비 서바이벌 게임 멀티플레이 하자(1)

by 27일 낮 2022. 6. 7.
728x90
  • RPC(Remote Procedure Call, 원격 프로시저 호출)
    • 호스트에 처리를 위임하고, 호스트가 처리 결과를 클라이언트에 전파하려면 RPC를 구현해야 함
    • 어떤 메서드나 처리를 네트워크를 넘어 다른 클라이언트에서 실핸하는 것
    • 대부분의 멀티플레이어 API에는 RPC가 구현되어 있음
  • 포톤 PUN(Photon Unity Networking)

 


 

지난번 좀비 서바이벌 프로젝트를 복제해서 Multi를 따로 만들어주자

 

 

 

에셋스토어에 들어가자

pun 이라고만 검색해도 나옴

 

 

 

 

우리가 쓸 건 PUN 2 - FREE ~!~!~!

https://assetstore.unity.com/packages/tools/network/pun-2-free-119922

 

PUN 2 - FREE | 네트워크 | Unity Asset Store

Get the PUN 2 - FREE package from Exit Games and speed up your game development process. Find this & other 네트워크 options on the Unity Asset Store.

assetstore.unity.com

내 에셋에 추가하기 - 승인 - Unity에서 열기 - Unity Editor 열기

 

 

 

Download - Import

 

 

 

처음 가져오는 패키지는 무조건 다 Import해주는 걸 권장

 

우선 PUN Wizard는 x를 눌러 꺼주자

 

 

 

Window - Photon Unity Networking 이 있어야 제대로 Import된 것

 

 

만약 없다면 Assets - Reimport All 을 눌러준다

 

 


https://www.photonengine.com/ko-KR/

 

글로벌 크로스 플랫폼 실시간 게임 개발 | Photon Engine

Cookie 설정 Photon은 귀하를 로그인 사용자로 식별하고 품질을 개선하고 마케팅을 위해 쿠키를 사용합니다. 아래 Cookie 설정을 확인하고 프라이버시를 관리해 주시기 바랍니다. 당사가 Cookie를 사용

www.photonengine.com

 

포톤 이용하려면 회원가입 해야 함!

회원가입하고 에디터로 ㄱㄱ

 

 

 

Window - Photon Unity Networking - Pun Wizard

 

 

 

Setup Project

 

 

이메일을 적어보자

근데 적으면 안 됨 ㅠ

다른 방법

 

 

다시 포톤으로 들어오자

새 어플리케이션 만들기

 

 

Photon 종류는 PUN으루

 

 

이름과 설명은 맘대루 쓰고 작성하기를 누르자

 

 

 

만들어졌다!

상세 정보에 들어가자

 

 

여기서 중요한 건 어플리케이션 ID임 쟤를 복사해오자

 

 

 

 

그리고 다시 에디터로 돌아와서 저기 붙여놓기 해주면 됨

Setup Project를 누르자

 

 

짜잔 그럼 얘가 생김

 

 

근데 확인을 한번 더하자

Inspector뷰에서 Server/Cloud Settings - App Id PUN 에서 아이디 적혀있는지 확인

없다면 적어주자

 

 

Dev Region 에 KR 적어주자

 


로비를 만들어보자

매치메이킹 서버 : 자동 대전 찾기st

    1) 빈 방 검색 -> 누군가가 만든 방 있으면 접속

    2) 빈 방이 없으면 본인이 호스트가 되어 방 만듦

 

 

Create - Scene -> Lobby 씬을 만들어주자

 

로비 씬으로 들어가서

Canvas를 만들자

Canvas는 기본 설정으로 그대로 둠

 

 

Canvas 안에 Panel 추가, 그 안에 Test - TextMeshPro 추가

TextMeshPro 이름은 Title Text

Title Text 복제 해서 이름을 Connection Info Text

 

 

그리고 또 Panel 안에 UI -> Button - TextMeshPro 만들어주고 이름은 Join Button

 

 

이제 상세 설정 해보자

 

 

Panel

하얗게 만들어주자

 

 

 

Connection Info Text, Join Button 는 일단 비활성화

Title Text에 Zombie Survival 작성해주자

 

 

앵커프리셋 적용해주자

Alt + Shift

 

 

 

폰트를 만들어주자

 

 

영어만 쓸거라서 Character Set을 아스키로 바꿔줌

Generate Font Atlas

 

 

확인하고 세이브~

 

 

와 생겼당

폰트 적용!

이제 폰트 스타일, 색상 등 맘대루

 


 

이제 Connection Info Text 활성화

앵커프리셋부터 적용 Alt + Shift 중앙

Width, Height 설정도 해주자

 

 

한글 폰트 다운 받아서 Fonts 폴더에 넣어주자

 

 

한글 폰트 만들어보자

다 만들고 세이브

 

 

 

 

 

버튼도 앵커프리셋 중앙으로 해주자

 

 

위치랑 크기 맞춰줌

 

 

 

 

그리고 버튼은 Interatable 체크 해제 해주어야 함!

스크립트에서 매치메이킹 서버에 정상적으로 접속된 상태에서만 버튼 컴포넌트의 Interactable을 true로 전환할 것임!

 

 

빈 오브젝트를 만들자 이름은 LobbyManager

LobbyManager.cs를 생성해서 여기 할당해주자

 

 

 

근데 사실 위에서 폰트 적용이 안됐었는데 LobbyManager 생성하니까 됐음 뭐임..?

그래서 걍 Reimport all 해주었따

 

 


LobbyManager.cs

using Photon.Pun; // 유니티용 포톤 컴포넌트
using Photon.Realtime; // 포톤 서비스 관련 라이브러리
using UnityEngine;
using UnityEngine.UI;
using TMPro;

// 마스터(매치메이킹) 서버와 룸 접속 담당
public class LobbyManager : MonoBehaviourPunCallbacks
{
    private string gameVersion = "1"; // 게임 버전

    public TextMeshProUGUI connectionInfoText; // 네트워크 정보를 표시할 텍스트
    public Button joinButton; // 룸 접속 버튼

    // 게임 실행과 동시에 마스터 서버 접속 시도
    private void Start()
    {
        // 접속에 필요한 정보(게임 비전) 설명
        PhotonNetwork.GameVersion = gameVersion;
        // 설정한 정보로 마스터 서버 접속 시도
        PhotonNetwork.ConnectUsingSettings();

        // 룸 접속 버튼 잠시 비활성화
        joinButton.interactable = false;
        // 접속 시도 중임을 텍스트로 표시
        connectionInfoText.text = "마스터 서버 접속 중...";
    }

    // 마스터 서버 접속 성공 시 자동 실행
    public override void OnConnectedToMaster()
    {
        // 룸 접속 버튼 활성화
        joinButton.interactable = true;
        // 접속 정보 표시
        connectionInfoText.text = "온라인 : 마스터 서버와 연결됨";
    }

    // 마스터 서버 접속 실패 시 자동 실행
    public override void OnDisconnected(DisconnectCause cause)
    {
        // 룸 접속 버튼 비활성화
        joinButton.interactable = false;
        // 접속 정보 표시
        connectionInfoText.text = "오프라인 : 마스터 서버와 연결되지 않음\n접속 재시도 중...";

        // 마스터 서버로의 재접속 시도
        PhotonNetwork.ConnectUsingSettings();
    }

    // 룸 접속 시도
    public void Connect()
    {
        // 중복 접속 시도를 막기 위해 접속 버튼 잠시 비활성화
        joinButton.interactable = false;

        // 마스터 서버에 접속 중이라면
        if (PhotonNetwork.IsConnected)
        {
            // 룸 접속 실행
            connectionInfoText.text = "룸에 접속...";
            PhotonNetwork.JoinRandomRoom();
        }
        else
        {
            // 마스터 서버에 접속 중이 아니라면 마스터 서버에 접속 시도
            connectionInfoText.text = "오프라인 : 마스터 서버와 연결되지 않음\n접속 재시도 중...";
            // 마스터 서버로의 재접속 시도
            PhotonNetwork.ConnectUsingSettings();
        }
    }

    // (빈 방이 없어) 랜덤 룸 참가에 실패한 경우 자동 실행
    public override void OnJoinRandomFailed(short returnCode, string message)
    {
        // 접속 상태 표시
        connectionInfoText.text = "빈 방이 없음, 새로운 방 생성...";
        // 최대 4명을 수용 가능한 빈 방 생성
        PhotonNetwork.CreateRoom(null, new RoomOptions { MaxPlayers = 4 });
    }

    // 룸에 참가 완료된 경우 자동 실행
    public override void OnJoinedRoom()
    {
        // 접속 상태 표시
        connectionInfoText.text = "방 참가 성공";
        // 모든 룸 참가자가 Main 씬을 로드하게 함
        PhotonNetwork.LoadLevel("Main");
    }
}
  • Photon.Realtime : 포톤의 실시간 네트워크 게임 개발용 C# 라이브러리
  • Photon.Pun : Photon.Realtime을 포함한 여러 포톤 C# 라이브러리를 유니티 게임 오브젝트와 컴포넌트로 사용할 수 있게 하는 PUN 라이브러리
  • MonoBehaviourPunCallbacks : MonoBehaviour 확장한 클래스. Photon.Pun에서 제공
    • MonoBehaviour 의 기능을 유지한 채 컴포넌트가 포톤 서비스에 의해 발생하는 콜백(이벤트나 메시지)도 감지
  • PhotonNetwork.LoadLevel() 메서드 : 룸의 플레이어들이 '함께 새로운 무대로 이동'하는 메서드

 

 

 

 

LobbyManager 스크립트에 할당

 

 

Join Button - On Click() 에 LobbyManager.Connect 추가

 

 

 


네트워크 플레이어 캐릭터를 준비해보자

 

 

 

Player Character 에 Photon View 추가

  • Photon View 컴포넌트 : 로컬과 리모트 구분 가능, 다른 클라이언트에 있는 '다른 버전의 자신'에게 관측된 수치를 전달하고 동기화할 수 있음
    • 네트워크를 통해 동기화될 모든 게임 오브젝트는 Photon View 컴포넌트를 가져야 함!
    • 게임 오브젝트에 네트워크상에서 구별 가능한 식별자인 View ID를 부여함
      (할당된 View ID는 네트워크 게임 오브젝트 수, 오브젝트가 생성된 순서 등에 따라 달라질 수 있음)
    • Observed Components 리스트에 등록된 컴포넌트들의 변화한 수치를 관측하고, 네트워크를 넘어서 다른 클라이언트에 전달할 수 있음
      (모든 컴포넌트가 관측 가능한 건 아님. IPunObservable 인터페이스를 상속한 컴포넌트만 관측 가능)
      • Observed Components 동기화 방법
        • Off : 동기화 X
        • Reliable Delta Compressed : 상대방이 최근에 수신한 값과 동일한 값은 송신하지 않음
        • Unreliable : 패킷의 수신 여부를 검사하지 않고 지속적으로 송신
        • Unreliable On Change : Unreliable과 동일하나 값의 변화가 감지될 때만 송신함

 

 


 

 

Photon Trasform View 컴포넌트 추가

: 자신의 게임 오브젝트에 추가된 트랜스폼 컴포넌트 값의 변화를 측정하고, Photon View 컴포넌트를 사용해 동기화 함

(Photon View 컴포넌트 없이는 동작할 수 없음!!)

 

Postition, Rotation 동기화하도록 설정

 

  • 자신이 로컬이라면 트랜스폼 컴포넌트의 속성값들을 감지하고 Photon View 컴포넌트를 사용해 네트워크 너머의 리모트로 보냄
  • 자신이 리모트라면 Photon View 컴포넌트를 사용해 송신된 로컬의 값을 받아 자신의 트랜스폼 컴포넌트에 적용함

 

 


 

Photon Animator View 컴포넌트 추가

: 네트워크를 넘어 로컬 게임 오브젝트와 리모트 게임 오브젝트 사이에서 애니메이터 컴포넌트의 파라미터를 동기화하여 서로 같은 애니메이션을 재생하도록 함

 

  • Photon Animator View 컴포넌트가 로컬일 때는 자신의 애니메이터 컴포넌트의 파라미터들을 관측하고, Photon View 컴포넌트를 사용해 다른 클라이언트에 있는 자신의 리모트에 전달함
  • 리모트일 때는 네트워크를 통해 로컬이 건넨 수치들을 받아 자신의 애니메이터 컴포넌트의 파라미터를 덮어쓰기 함
  • 동기화를 원하느는 파라미터는 드롭다운 메뉴를 클릭하고 Discrete 또는 Continuous로 동기화 옵션 설정
    • Discrete는 값의 연속적인 변화를 Continuous에 비해 잘 반영하지 못하지만 대역폭을 아낄 수 있음
    • 동기화 할 필요 없는 경우엔 Disabled로 설정하여 대역폭 아낄 수 있음

 

 


CameraSetup.cs 추가

 

이 스크립트는 씬의 시네머신 가상 캄라가 로컬 플레이어만 추적하도록 설정할 거임!

따라서 자신의 게임 오브젝트가 로컬 게임 오브젝트인지 검사해야 함

 

댓글