//UI
public TMP_InputField id_InputField;
public TMP_InputField room_InputField;
TMP 관련 UI들은 선언시 형식명이 다르다
앞에 TMP_ 가 붙게 된다
그냥 InputField 등을 써서 한다면 호환되지 않는다

auto size
버튼등에서 글자 사이즈를 딱맞게 만들어준다

Text쪽에서 자동 줄바꿈 on/off
______________________________________________________
PhotonNetwork.IsMessageQueueRunning = false;
씬 이동할 때, 서버로부터 메세지 안받게 했다가
씬 이동 끝나면
PhotonNetwork.IsMessageQueueRunning = true;
다시 받게 해야하는데,
LoadLevel로 이동하면 저걸 자동으로 다 해준다
___________________________________________________________
방 생성, 삭제 등
방 목록 관리
탱크에서 이미 한번 했었지만 다시 한번

방 목록 띄울 스크롤뷰 생성
public class RoomData : MonoBehaviourPun
{
private RoomInfo _info;
public TMP_Text roomNameText;
public Button roomBtn;
public RoomInfo RoomInfo
{
get
{
return _info;
}
set
{
_info = value;
roomNameText.text = $"{_info.Name} ( {_info.PlayerCount} / {_info.MaxPlayers} )";
}
}
}
프로퍼티를 이용해서 값을 할당할때 자동으로 ui내용이 바뀔수있도록 했다.
button은 본인 자체라서 그냥 GetComponent해도 된다.

public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
GameObject tempRoom = null; // 삭제된 방의 정보를 담기 위한 것
//여기에 들어왔다는거 부터가 뭔가 룸 정보는 바뀐거임
foreach (var roomInfo in roomList) //룸들 전체 체크
{
if (roomInfo.RemovedFromList)//이 방이 삭제된 적이 있다면(안에 유저가 0명이 되거나 해서)
{
roomsDic.TryGetValue(roomInfo.Name, out tempRoom); // Dictionary를 이용해서, key값인 string을 이용해서 그 방이 있는지 찾는다
Destroy(tempRoom); // 그 방의 GameObject삭제(화면에서 안보이게 된다)
this.roomsDic.Remove(roomInfo.Name); // dictionary에서도 제거
}
else//뭔가 변경은 됐는데 그게 삭제는 아니라면
{
if (!roomsDic.ContainsKey(roomInfo.Name)) // dictionary에 그 방이 있는지 체크해서
// 없다면 -> 신규 추가된 방
{
GameObject room = Instantiate(this.roomItemPrefab,this.contents);
var data = room.GetComponent<RoomData>();
data.RoomInfo = roomInfo; // 프로퍼티 식으로 되어있기 때문에 방 버튼의 Text는 이 코드에서 알아서 바뀜
data.roomBtn.onClick.AddListener(() =>
{
SetUserId();
PhotonNetwork.JoinRoom(roomInfo.Name);
});
this.roomsDic.Add(roomInfo.Name, room);
}
else //변경은 됐는데 이미 있던 방임 -> 인원수 등이 바뀜
{
roomsDic.TryGetValue(roomInfo.Name, out tempRoom);
tempRoom.GetComponent<RoomData>().RoomInfo = roomInfo;
}
}
}
}
이 함수는 MonoBehaviourPunCallbacks 안에 있는거고, 방의 정보가 조금이라도 변화하면 자동으로 호출된다
매개변수로 들어오는 방 List전부 체크해서, 이게 지워졌는지, 안지워졌다면 원래 없던건지, 있던거라면 그냥 상세 내용이 바뀐거니 내용을 변경하는 식으로 구현한다.
public void OnClickLoginBtn() // 로그인 버튼 눌러서, 유저 이름 인풋과 방 이름 인풋 체크해서 로그인 시키기
{
SetUserId();
//PhotonNetwork.IsMessageQueueRunning = false; // LoadLevel로 씬을 이동하고 있어서 이걸 포함하지 않아도 된다.
if (!string.IsNullOrEmpty(this.room_InputField.text)) // 방 이름까지 쳤을때
{
/*if (this.roomsDic.ContainsKey(this.room_InputField.text)) // 그 방이 있다면
{
PhotonNetwork.JoinRoom(this.room_InputField.text);
}
else // 없다면
{
MakeRoom(this.room_InputField.text); // 그 이름의 방 생성
}*/
PhotonNetwork.JoinOrCreateRoom(this.room_InputField.text, new RoomOptions() { IsOpen = true, IsVisible = true, MaxPlayers = 20 }, TypedLobby.Default);
}
else
{
//안쳤을때
if (PhotonNetwork.CountOfRooms <= 0) // 방이 없다면
{
room_InputField.text = "God Chang Seop";
MakeRoom(this.room_InputField.text);
//디폴트 방 생성
}
else//방이 있다면
{
PhotonNetwork.JoinRandomRoom();
}
}
}
public void OnClickLoginBtn() // 로그인 버튼 눌러서, 유저 이름 인풋과 방 이름 인풋 체크해서 로그인 시키기
{
SetUserId();
//PhotonNetwork.IsMessageQueueRunning = false; // LoadLevel로 씬을 이동하고 있어서 이걸 포함하지 않아도 된다.
if (!string.IsNullOrEmpty(this.room_InputField.text)) // 방 이름까지 쳤을때
{
/*if (this.roomsDic.ContainsKey(this.room_InputField.text)) // 그 방이 있다면
{
PhotonNetwork.JoinRoom(this.room_InputField.text);
}
else // 없다면
{
MakeRoom(this.room_InputField.text); // 그 이름의 방 생성
}*/
PhotonNetwork.JoinOrCreateRoom(this.room_InputField.text, new RoomOptions() { IsOpen = true, IsVisible = true, MaxPlayers = 20 }, TypedLobby.Default);
}
else
{
//안쳤을때
if (PhotonNetwork.CountOfRooms <= 0) // 방이 없다면
{
room_InputField.text = "God Chang Seop";
MakeRoom(this.room_InputField.text);
//디폴트 방 생성
}
else//방이 있다면
{
PhotonNetwork.JoinRandomRoom();
}
}
}
로그인 버튼 클릭 내용
룸이 있는지 체크해서 들어가거나 방을 만들거나 로 만들었는데
joinOrCreateRoom이라는 메서드가 이미 있었다
___________________________________________________________________
캐릭터 생성 시기 문제
public class GameManager : MonoBehaviourPun
{
public Volume volume;
IEnumerator Start()
{
while (!PhotonNetwork.InRoom)
{
yield return null;
}
//PhotonNetwork.IsMessageQueueRunning = true; // LoadLevel로 이동하고 있어서 이 코드를 포함하지 않아도 된다.
CreatePlayer();
}
private void CreatePlayer()
{
Transform[] points = GameObject.Find("SpawnPoints").GetComponentsInChildren<Transform>();
int idx = Random.Range(1, points.Length);
PhotonNetwork.Instantiate
("Player",
points[idx].position,
Quaternion.identity
);
DepthOfField dof;
this.volume.profile.TryGet<DepthOfField>(out dof);
dof.active = false;
}
}
저 Start가 원래 그냥 void였고, 그냥 바로 CreatePlayer를 실행하게 했었는데,
방에 들어가기도 전에 실행되서 Instantiate가 방에 들어가기도 전에 작동하고, 그 결과 다른 사람들에게 캐릭터가 안보이는 문제가 있었다
RaiseEvent(202) failed. Your event is not being sent! Check if your are in a Room
그래서 ienumerator로 바꾸고, 룸에 들어가기 전까지 while문 안에서 돌려서 room에 들어가고 나서 생성되게 바꿨다
______________________________________________________________________

Dev Region -> 유니티 에디터상의 지역
저거 잘못 설정하면 빌드파일이랑 에디터랑 지역이 달라서 서로 못만나는 경우가 생길 수 있음
______________________________________________________________________
public class RoomItem : MonoBehaviour
{
[SerializeField] RoomInfo _roomInfo;
[SerializeField] TMP_Text roomInfoText;
[SerializeField] PhotonManager photonManager;
public RoomInfo RoomInfo
{
get { return _roomInfo; }
set
{
_roomInfo = value;
roomInfoText.text = $"{_roomInfo.Name} ({_roomInfo.PlayerCount} / {_roomInfo.MaxPlayers})";
// 동적 이벤트 리스너 구현해서 눌렀을때 해당 룸에 접속
GetComponent<UnityEngine.UI.Button>().onClick.AddListener(() => OnEnterRoom(_roomInfo.Name));
}
}
이게 원래 있던 코드
프로퍼티를 통해 값을 할당할때 버튼쪽에 이벤트를 추가했었다
이 코드는 에디터에선 에러 메세지가 나왔고 빌드파일에선 에러가 뜨지 않았다
else // 룸 정보가 변경된 경우 // 생성하는 로직
{ // 룸 이름이 딕셔너리에 없는 경우 새로 생성
if(rooms.ContainsKey(roomInfo.Name) == false) // 비교를 해서 있는지 없는지 검사
{
// RoomItem 프리팹을 scrollContents 하위에 생성
GameObject roomPrefabs = Instantiate(roomItemPrefab, scrollContents);
// 룸 정보를 표시하기 위해 RoomInfo 정보 전달
roomPrefabs.GetComponent<RoomItem>().RoomInfo = roomInfo;
roomPrefabs.GetComponent<Button>().onClick.AddListener(() =>
{
SetUserId();
PhotonNetwork.JoinRoom(roomInfo.Name);
});
// 딕셔너리 자료형에 데이터 추가
rooms.Add(roomInfo.Name,roomPrefabs);
}
바꾼 코드
이벤트 추가부분을 다른 코드쪽에서 직접 하게했으며, 이벤트 추가 또한 값 할당이 전부 끝난 뒤에 하게 되었다
에러는 고쳐졌지만
RaiseEvent(201) failed. Your event is not being sent! Check if your are in a Room
이런 경고가 뜨게 되었다
나가지고 난 뒤에 뭔가 포톤 내부에서 일어나는 코드로 나오는 내용이다
그냥 해도 별 상관은 없는 내용이지만
this.exitBtn.onClick.AddListener(() =>
{
dof.active = true;
//PhotonNetwork.LeaveRoom();
StartCoroutine(LeaveRoomSmooth());
});
}
IEnumerator LeaveRoomSmooth()
{
PhotonNetwork.LeaveRoom();
yield return new WaitUntil(() => !PhotonNetwork.InRoom);
SceneManager.LoadScene(0);
}
leaveRoom을 이용해서 자동으로 콜백되는 onLeftRoom 에서 씬을 로드하는게 아닌,
InRoom이 아닐때까지 기다린다음 -> 방에서 나가질때까지 기다린다음 씬을 로드하면 경고도 뜨지않는다
-> 수정
this.exitBtn.onClick.AddListener(() =>
{
dof.active = true;
//PhotonNetwork.LeaveRoom();
//StartCoroutine(LeaveRoomSmooth());
PhotonNetwork.LeaveRoom();
SceneManager.LoadScene(0);
});
그냥 OnLeftRoom을 쓰면 나오게 되는 경고였다
안쓰니까 안난다