카테고리 없음

0718 유니티(TMP)

버스창문 2025. 7. 18. 09:56
    //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해도 된다.

 

 

 

roomItem 내용

 

 

 

    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을 쓰면 나오게 되는 경고였다

안쓰니까 안난다