日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

项目实训--Unity多人游戏开发(十、游戏GUI界面与PUN大厅房间)

發布時間:2023/12/18 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 项目实训--Unity多人游戏开发(十、游戏GUI界面与PUN大厅房间) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 界面設計
    • GUI與PUN代碼結構(調用關系)
    • 項目代碼
      • 官方demo學習結果
      • 官方文檔學習筆記--退出房間(與實際需求有偏差,可不看)
    • 待更新點及總結

界面設計

初始界面
背景暫時放一張糖豆人的海報,界面這部分是和小組其他成員一起制作的。其他成員的博客可以在小組的綜述里找到。

登錄注冊
請忽略后面的黃色字體和充滿違和感的素材。還沒有到GUI美化階段。

大廳界面
創建房間界面
見下下下面↓


GUI與PUN代碼結構(調用關系)

AppManager.cs負責各種監聽函數、GUI顯示邏輯等。
Launcher.cs繼承PunCallbacks,實現Pun相關的內容。
這兩部分代碼搭配使用。
GUI操作→調用pun;
pun結果→GUI反饋。


項目代碼

下面進行大廳功能的開發。
當加入主服務器后,我們需要的功能是加入大廳并且顯示房間列表而不是直接隨機加入到某個房間中。
而且如果要進行創建房間,必須要先在大廳/主服務器中才可以。
修改OnConnectedToMaster回調:

public override void OnConnectedToMaster(){Debug.Log("連接到主服務器! this msg is from `OnConnectedToMaster()`");//GUI提示--message:歡迎上線!//UI.Show("歡迎上線");PhotonNetwork.JoinLobby();//連接大廳lobbyPanel.gameObject.SetActive(true);//開啟大廳面板startPanel.gameObject.SetActive(false);//關閉登錄面板}

lobbyPanel:(粗略的制作了一下,GUI美化在后期)


中間的列表區域是一個Unity的UI對象ScrollView。(已刪除水平滾動條)
房間會被加入到Content中顯示,別忘了給Content加一個GridLayoutGroup組件。并且調整內部元素的大小。


房間列表的顯示可以通過pun官方的回調函數OnRoomListUpdate來寫。

public override void OnRoomListUpdate(List<RoomInfo> roomList){for (int i = 0; i < gridLayoutGroup_content.childCount; i++){if (gridLayoutGroup_content.GetChild(i).gameObject.GetComponentInChildren<Text>().text == roomList[i].Name)//防止重復的房間顯示{Destroy(gridLayoutGroup_content.GetChild(i).gameObject);}if (roomList[i].PlayerCount == 0)//剔除房間人數為0的房間顯示{roomList.Remove(roomList[i]);}}foreach (var room in roomList)//顯示在list中的每個房間{//這里在學習官方demo后有改動。主要是房間預制體更詳細了。//此處大致略過即可。GameObject newRoom = Instantiate(roomPrefab, gridLayoutGroup_content.position, Quaternion.identity);newRoom.GetComponentInChildren<Text>().text = room.Name + "(" + room.PlayerCount + "/" + room.MaxPlayers + ")";//UI設置父物體,添加在畫布上。newRoom.transform.SetParent(gridLayoutGroup_content);}}

點擊創建房間后會彈出創建面板。

確定按鈕的監聽。

public void SureCreateBtn(){AudioManager.instance.Click();if (roomNameInputField.text.Length<2){//UI提示房間名不規范return;}Launcher.instance.CreateRoom(roomNameInputField.text,4);//第二個參數是byte類型,暫時默認為4}

現在已經可以建立房間和顯示房間了,但是還沒有制作加入房間等功能。
另外提示一下,unity中導入Pun2插件后,可以找到官方的demo,里面具有游戲同步和房間大廳的代碼,如下圖

當然再Scenes里可以找到場景并且進行多人游玩。(前提是配置好pun的AppID等)


官方demo學習結果

通過上述官方demo的學習。
先講一下大致框架:
創建房間后仍然調用Photon的官方API。
這里因為房間需要復用。把房間作為一個預制體。

這里只顯示最基本的房間信息以及一個按鈕。
有其他需要可以擴展。不過要結合pun框架哦。

在之前的OnRoomListUpdate回調里,需要改一下了:

public override void OnRoomListUpdate(List<RoomInfo> roomList){//...這些代碼沒變//變動↓foreach (var room in roomList)//顯示在list中的每個房間{GameObject entry = Instantiate(roomEntryPrefab, gridLayoutGroup_content.position, Quaternion.identity);entry.transform.SetParent(gridLayoutGroup_content);//entry.transform.localScale = Vector3.one;//調用entry(預制體)上掛的腳本的初始化方法,把房間名等信息傳到UI。entry.GetComponent<RoomEntry>().Initialize(room.Name, (byte)room.PlayerCount, room.MaxPlayers);}}

然后這樣列表里會逐一顯示“房間名稱”、“在線人數/最大人數”、“加入按鈕”的房間。
具體RoomPrefab內部布局這里不提及。UI按照個人意愿做就好了。可以使用UI的一些布局組件“Horizontal Layout Group”。

然后看一下掛在RoomPrefab上的腳本:
RoomEntry.cs:

//省略命名空間引用和類名//預制體上的三個元素public Text RoomNameText;public Text RoomPlayersText;public Button JoinRoomButton;//私有變量存儲房間名private string roomName;//unity的回調public void Start(){//給按鈕添加監聽JoinRoomButton.onClick.AddListener(() =>{if (PhotonNetwork.InLobby){PhotonNetwork.LeaveLobby();//加入房間時離開大廳}//加入這個房間,roomName來自Initialize方法//可回看OnRoomListUpdate回調的改動PhotonNetwork.JoinRoom(roomName);});}//由外部實例化一個房間的時候調用,更新這個預制體的信息public void Initialize(string name, byte currentPlayers, byte maxPlayers){roomName = name;RoomNameText.text = name;RoomPlayersText.text = currentPlayers + " / " + maxPlayers;}

現在可以生成房間并且顯示房間了。
那么創建房間或點擊加入房間之后該顯示什么呢?
下一步制作RoomPanel。

這個panel不需要做成預制體,根本不需要復用,用SetActive(bool)控制它的顯示與否就可以了。
預制體包含:

  • 房間名稱的文本(可不要)
  • 離開房間按鈕
  • 開始房間按鈕(默認不顯示,通過代碼實現當全部玩家準備好后在房主那邊顯示)。
  • 另外最重要的就是顯示玩家了,而且還要有準備功能!
    為此創建一個PlayerEntryPrefab。


    共四個子UI:
    一個用于區分玩家的顏色顯示塊。
    玩家昵稱。
    準備與取消準備按鈕。
    準備狀態圖片。

    但是代碼就復雜起來了。也需要用到更高深的API。
    如何知道玩家有沒有準備?如何同步準備信息?如何給定當前房間的玩家一個永久對應的顏色?
    官方demo是這么做的(有少許改動):
    PlayerEntry腳本,掛在預制體上:

    //PlayerEntry.cspublic void Start(){if (PhotonNetwork.LocalPlayer.ActorNumber != ownerId){Debug.Log("這不是我,隱藏準備按鈕,PlayerEntry.Start-ActorNumber!=ownerId");PlayerReadyButton.gameObject.SetActive(false);}else{Hashtable initialProps = new Hashtable() { { Const.Player_Ready, isPlayerReady }, { Const.PLAYER_LIVES, Const.PLAYER_MAX_LIVES } };PhotonNetwork.LocalPlayer.SetCustomProperties(initialProps);PhotonNetwork.LocalPlayer.SetScore(0);PlayerReadyButton.onClick.AddListener(() =>{isPlayerReady = !isPlayerReady;SetPlayerReady(isPlayerReady);//把個人信息準備情況的信息寫到CustomProperties里Hashtable props = new Hashtable() { { Const.Player_Ready, isPlayerReady } };PhotonNetwork.LocalPlayer.SetCustomProperties(props);if (PhotonNetwork.IsMasterClient){//我是房主的話,執行一下OnePlayerReady,檢測一下是不是全準備了//全準備了就顯示開始游戲按鈕FindObjectOfType<Launcher>().OnePlayerReady();//Launcher.instance.OnePlayerReady();}});}}public void SetPlayerReady(bool playerReady){PlayerReadyButton.GetComponentInChildren<Text>().text = playerReady ? "Ready!" : "Ready?";PlayerReadyImage.enabled = playerReady;}

    傳遞每個客戶端的消息(準備情況),用的是SetCustomProperties,這都是pun封裝好的方法,用來修改這個玩家對應的一些屬性,有監聽修改的回調函數。玩家屬性有改動則會執行這個回調。可以檢測有沒有都準備。
    OnPlayerPropertiesUpdate():

    public override void OnPlayerPropertiesUpdate(Photon.Realtime.Player targetPlayer, Hashtable changedProps)//其他玩家點擊準備--提交到定制特性時,本地調用回調更新界面{if (playerListEntries == null){playerListEntries = new Dictionary<int, GameObject>();}GameObject entry;//從玩家字典里獲取對應玩家if (playerListEntries.TryGetValue(targetPlayer.ActorNumber, out entry)){object isPlayerReady;if (changedProps.TryGetValue(Const.Player_Ready, out isPlayerReady)){//更新本地UI上這個玩家準備狀態entry.GetComponent<PlayerEntry>().SetPlayerReady((bool)isPlayerReady);}}//檢測一下是不是全準備了,是的話房主顯示啟動按鈕AMinstance.startGameBtn.gameObject.SetActive(CheckPlayersReady());}

    由以上代碼,當全部玩家準備后,房主那邊才可以點擊開始游戲。
    開始游戲按鈕的監聽里可以調用PhotonNetwork.LoadLevel("SceneName");,啟動游戲場景。按照前幾篇博文,只要開啟了同步加載場景,那么其他玩家會同步加載游戲。


    官方文檔學習筆記–退出房間(與實際需求有偏差,可不看)

    首先要明確不同人數的游戲房間,地形大小也是不同的,軟件應該為用戶帶來良好體驗,而游戲中有足夠大的空間會增強這一點。

    還要實現一個退出房間的功能,先做一個GameManager預制體并附上一個腳本(不同場景中會復用GameManager),腳本包含點擊事件對應的函數LeaveRoom及退出房間的回調函數OnLeftRoom。
    同時做一個按鈕預制體。為其監聽器添加LeaveRoom。

    按鈕制作這里可以修改RectTransform的錨點,按shift和alt鍵設置為top和stretch。RectTransform是UI特有組件。這里涉及到錨點/錨框的知識點,說白了就是相對布局與絕對布局的概念。

    然后我們需要玩家加入或退出房間后加載場景,這用到兩個回調函數OnPlayerEnteredRoom和OnPlayerLeftRoom。代碼如下

    public override void OnPlayerEnteredRoom(Player other) {Debug.LogFormat("OnPlayerEnteredRoom() {0}", other.NickName); // not seen if you're the player connectingif (PhotonNetwork.IsMasterClient){Debug.LogFormat("OnPlayerEnteredRoom IsMasterClient {0}", PhotonNetwork.IsMasterClient); // called before OnPlayerLeftRoomLoadArena();} }public override void OnPlayerLeftRoom(Player other) {Debug.LogFormat("OnPlayerLeftRoom() {0}", other.NickName); // seen when other disconnectsif (PhotonNetwork.IsMasterClient){Debug.LogFormat("OnPlayerLeftRoom IsMasterClient {0}", PhotonNetwork.IsMasterClient); // called before OnPlayerLeftRoomLoadArena();} }#region Private Methods void LoadArena() {if (!PhotonNetwork.IsMasterClient){Debug.LogError("PhotonNetwork : Trying to Load a level but we are not the master Client");}Debug.LogFormat("PhotonNetwork : Loading Level : {0}", PhotonNetwork.CurrentRoom.PlayerCount);PhotonNetwork.LoadLevel("Room for " + PhotonNetwork.CurrentRoom.PlayerCount); } #endregion

    要注意PhotonNetwork.LoadLevel是只有房主才能調用的方法。當所有客戶端開啟了同步加載場景后會自動跟隨加載場景。
    官方文檔到此之后的代碼與要完成的功能有點區別。
    有一點要注意的是必要時可以用一個bool變量存儲用戶的連接狀態并作為后續代碼執行條件。避免用戶在退出房間時執行了并不需要的功能。

    bool isConnecting; //... isConnecting = PhotonNetwork.ConnectUsingSettings();

    待更新點及總結

    至于玩家顏色方面
    通過Photon.Realtime.Player.GetPlayerNumber()玩家編號來獲得不同顏色。

    //PlayerEntry.cspublic void OnEnable(){PlayerNumbering.OnPlayerNumberingChanged += OnPlayerNumberingChanged;}public void OnDisable(){PlayerNumbering.OnPlayerNumberingChanged -= OnPlayerNumberingChanged;}//委托對應的方法,每當玩家編號發生變化時調用?//ownerId是私有變量。private void OnPlayerNumberingChanged(){foreach (Photon.Realtime.Player p in PhotonNetwork.PlayerList){if (p.ActorNumber == ownerId){//修改UI上的顏色PlayerColorImage.color = Launcher.GetColor(p.GetPlayerNumber());}}}

    但是好像涉及到玩家編號改變的情況(玩家進入退出房間),demo用了委托,還額外有一個"PlayerNumbering.cs"腳本,暫時還沒看懂有什么用。
    后續有時間再看一下吧。

    下一步就可以學習游戲的同步了。這里才是重頭戲。將會新開一篇博文。

    總結

    以上是生活随笔為你收集整理的项目实训--Unity多人游戏开发(十、游戏GUI界面与PUN大厅房间)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。