Photon Pun2를 이용하여 2인 멀티 플레이 게임을 제작하고 있다.
Photon을 이용하여 매치메이킹을 구현하고자 한다.
매치 방식은 2가지다.
한 명이 초대 코드를 생성하면 다른 한 명이 초대 코드를 입력하여 같은 방에 입장할 수 있다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using Photon.Pun;
using Photon.Realtime;
public class MatchManager : MonoBehaviourPunCallbacks
{
[Header("UI")]
public TMP_InputField joinCodeInputField;
public TMP_Text statusText;
private const int MaxPlayer = 2;
private const int MaxRetry = 3;
private const int RoomCodeLen = 6;
private static readonly char[] RoomCodeChars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789".ToCharArray();
void Awake()
{
// 자동 씬 동기화
PhotonNetwork.AutomaticallySyncScene = true;
}
void Start()
{
if (!PhotonNetwork.IsConnected)
{
PhotonNetwork.ConnectUsingSettings();
statusText.text = "서버에 연결 중...";
}
}
public override void OnConnectedToMaster()
{
PhotonNetwork.JoinLobby();
statusText.text = "서버 연결 완료";
Debug.Log("Connected to Master");
}
// 1. 친구와 함께하기
public void OnClick_CreateRoom()
{
StartCoroutine(TryCreateRoom());
}
IEnumerator TryCreateRoom()
{
int retry = MaxRetry;
while (retry > 0)
{
string code = GenerateRoomCode();
RoomOptions options = new RoomOptions
{
MaxPlayers = MaxPlayer,
IsVisible = false,
IsOpen = true
};
PhotonNetwork.CreateRoom(code, options, TypedLobby.Default);
statusText.text = $"방 생성 중... 코드 {code}";
// Photon 응답 지연 시간
float elapsed = 0f;
const float timeout = 2f; // 테스트 후 조정 가능
while (!PhotonNetwork.InRoom && elapsed < timeout)
{
elapsed += Time.deltaTime;
yield return null;
}
if (PhotonNetwork.InRoom)
{
yield break;
}
retry--;
}
statusText.text = "방 생성 실패. 다시 시도해주세요.";
}
public void OnClick_JoinWithCode()
{
string code = joinCodeInputField.text.ToUpper();
if (code.Length != RoomCodeLen)
{
statusText.text = "코드는 6자리여야 합니다.";
return;
}
PhotonNetwork.JoinRoom(code);
statusText.text = $"{code} 방에 입장 중...";
}
private string GenerateRoomCode()
{
System.Text.StringBuilder code = new System.Text.StringBuilder();
for (int i = 0; i < RoomCodeLen; i++)
{
int index = Random.Range(0, RoomCodeChars.Length);
code.Append(RoomCodeChars[index]);
}
return code.ToString();
}
public override void OnJoinRoomFailed(short returnCode, string message)
{
statusText.text = "초대 코드가 잘못 되었거나 방이 꽉 찼어요!";
Debug.LogWarning($"JoinRoom 실패: {message}");
}
// 2.랜덤 매치
public void OnClick_RandomMatch()
{
PhotonNetwork.JoinRandomRoom();
statusText.text = "랜덤 매칭 중...";
}
public override void OnJoinRandomFailed(short returnCode, string message)
{
RoomOptions options = new RoomOptions
{
MaxPlayers = MaxPlayer,
IsVisible = true,
IsOpen = true
};
PhotonNetwork.CreateRoom(null, options);
statusText.text = "새 방 생성 중...";
}
public override void OnJoinedRoom()
{
statusText.text = $"방 입장. 현재 인원: {PhotonNetwork.CurrentRoom.PlayerCount}/{MaxPlayer}";
if (PhotonNetwork.CurrentRoom.PlayerCount == MaxPlayer)
{
Debug.Log("모든 플레이어 입장 완료. 게임 시작");
// 두 플레이어가 캐릭터 선택 씬으로 이동
PhotonNetwork.LoadLevel("Character");
}
}
// 연결 실패 시
public override void OnDisconnected(DisconnectCause cause)
{
statusText.text = "서버 연결 끊김: " + cause.ToString();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using Photon.Pun;
using Photon.Realtime;
using Photon.Pun;, using Photon.Realtime;
Photon Unity Networking (PUN) 관련 기능을 가져다 쓰기 위한 네임스페이스
RoomOptions), 로비 시스템 (TypedLobby), 매치 결과 처리 등에서 사용 가능 public TMP_InputField joinCodeInputField;
public TMP_Text statusText;
private const int MaxPlayer = 2;
private const int MaxRetry = 3;
private const int RoomCodeLen = 6;
private static readonly char[] RoomCodeChars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789".ToCharArray();
joinCodeInputField: 초대 코드를 입력 받을 TMP_InputField
statusText: 현재 상태(서버 연결, 방 입장 등)를 나타낼 TMP_Text
MaxPlayer: 최대 입장 가능한 플레이어 수
MaxRetry: 최대 방 생성 시도 횟수
RoomCodeLen: 초대 코드 길이
RoomCodeChars: 초대 코드에 들어갈 수 있는 영문자와 숫자 배열
void Awake()
{
// 자동 씬 동기화
PhotonNetwork.AutomaticallySyncScene = true;
}
void Start()
{
if (!PhotonNetwork.IsConnected)
{
PhotonNetwork.ConnectUsingSettings();
statusText.text = "서버에 연결 중...";
}
}
public override void OnConnectedToMaster()
{
PhotonNetwork.JoinLobby();
statusText.text = "서버 연결 완료";
Debug.Log("Connected to Master");
}
// 1. 친구와 함께하기
public void OnClick_CreateRoom()
{
StartCoroutine(TryCreateRoom());
}
IEnumerator TryCreateRoom()
{
int retry = MaxRetry;
while (retry > 0)
{
string code = GenerateRoomCode();
RoomOptions options = new RoomOptions
{
MaxPlayers = MaxPlayer,
IsVisible = false,
IsOpen = true
};
PhotonNetwork.CreateRoom(code, options, TypedLobby.Default);
statusText.text = $"방 생성 중... 코드 {code}";
// Photon 응답 지연 시간
float elapsed = 0f;
const float timeout = 2f; // 테스트 후 조정 가능
while (!PhotonNetwork.InRoom && elapsed < timeout)
{
elapsed += Time.deltaTime;
yield return null;
}
if (PhotonNetwork.InRoom)
{
yield break;
}
retry--;
}
statusText.text = "방 생성 실패. 다시 시도해주세요.";
}
InRoom을 체크하면 아직 false일 확률이 높으므로 몇 초 기다린 후 방에 입장했는지 확인한다.InRoom이 true가 안 되면 방 생성 실패로 간주하고 다시 시도한다.public void OnClick_JoinWithCode()
{
string code = joinCodeInputField.text.ToUpper();
if (code.Length != RoomCodeLen)
{
statusText.text = "코드는 6자리여야 합니다.";
return;
}
PhotonNetwork.JoinRoom(code);
statusText.text = $"{code} 방에 입장 중...";
}
OnJoinedRoom() 콜백 호출OnJoinRoomFailed() 콜백 호출private string GenerateRoomCode()
{
System.Text.StringBuilder code = new System.Text.StringBuilder();
for (int i = 0; i < RoomCodeLen; i++)
{
int index = Random.Range(0, RoomCodeChars.Length);
code.Append(RoomCodeChars[index]);
}
return code.ToString();
}
+=로 문자열을 추가하려고 할 때마다, 실제로는 새로운 문자열이 계속 생성되고 기존 것은 버려진다.public override void OnJoinRoomFailed(short returnCode, string message)
{
statusText.text = "초대 코드가 잘못 되었거나 방이 꽉 찼어요!";
Debug.LogWarning($"JoinRoom 실패: {message}");
}
JoinRandomRoom()을 사용하여 입장을 시도한다.JoinRandomRoom()을 통해 입장 실패 시 OnJoinRandomFailed이 호출된다.// 2.랜덤 매치
public void OnClick_RandomMatch()
{
PhotonNetwork.JoinRandomRoom();
statusText.text = "랜덤 매칭 중...";
}
OnJoinedRoom() 호출OnJoinRandomFailed() 호출 public override void OnJoinRandomFailed(short returnCode, string message)
{
RoomOptions options = new RoomOptions
{
MaxPlayers = MaxPlayer,
IsVisible = true,
IsOpen = true
};
PhotonNetwork.CreateRoom(null, options);
statusText.text = "새 방 생성 중...";
}
public override void OnJoinedRoom()
{
statusText.text = $"방 입장. 현재 인원: {PhotonNetwork.CurrentRoom.PlayerCount}/{MaxPlayer}";
if (PhotonNetwork.CurrentRoom.PlayerCount == MaxPlayer)
{
Debug.Log("모든 플레이어 입장 완료. 게임 시작");
// 두 플레이어가 캐릭터 선택 씬으로 이동
PhotonNetwork.LoadLevel("Character");
}
}
PhotonNetwork.AutomaticallySyncScene = true;