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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

使用Photon PUN创建简单对战游戏

發布時間:2023/12/18 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Photon PUN创建简单对战游戏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:

photon PUN是一款用于實現聯網對戰的插件,通過簡單的設計,就可以實現加入大廳,加入房間,并且進行對戰,玩家可以同步動畫和位置等參數,同時可以通過RPC機制,廣播參數,實現房間內的玩家消息共享。

對戰實現

1.打開photon官網,再打開賬號,登錄。

2.點擊Your Applications,創建應用,選擇PUN,按要求填寫,然后再復制Appid,打開unity創建項目。

3.在unity的資源商店中搜索photon PUN,下載導入。

4.粘貼剛才復制的appid,點擊setup project—close

5.新建一個場景,添加如下的UI組件,一個是名字輸入面板,點擊之后進入大廳。


6.在場景中新建一個空物體,命名NetWorkManager,同樣新建一個腳本NetworkManager,填充命名空間PUN,更改繼承類為MonoBehaviourPunCallbacks,首先在start函數中啟動。連接服務器,具體的代碼如下:

using System.Collections; using System.Collections.Generic; using UnityEngine; using Photon.Pun; using UnityEngine.UI; using Photon.Realtime;public class NetworkManager : MonoBehaviourPunCallbacks {#region 私有變量#endregion#region 公開變量public static NetworkManager _instance;//單例public InputField nameInputField;//名字輸入框public InputField RoomnameInputField;//房間名輸入框public GameObject readyBtn;//準備按鈕public GameObject startBtn;//開始游戲按鈕public GameObject NamePanel;//名字設置面板public GameObject LobbyPanel;//大廳面板public GameObject RoomPanel;//房間面板public GameObject StartInitPanel;//開始初始化面板#endregion#region Mono函數private void Awake(){if (_instance == null){_instance = this;}}private void Start(){PhotonNetwork.ConnectUsingSettings();//初始化設置,連接服務器}private void Update(){if (PhotonNetwork.LocalPlayer.IsMasterClient)//判斷是否是房主,是就顯示開始游戲按鈕,不是就顯示準備按鈕{readyBtn.SetActive(false);startBtn.SetActive(true);}else{readyBtn.SetActive(true);startBtn.SetActive(false);}}#endregion#region 按鈕函數/// <summary>/// 名字設置按鈕/// </summary>public void SetNicknameButton(){if (nameInputField.text.Length < 2)return;PhotonNetwork.NickName = nameInputField.text;//將輸入的名字上傳至網絡if(PhotonNetwork.InLobby)//判斷是否在大廳內,在就顯示大廳,隱藏名字面板{LobbyPanel.SetActive(true);NamePanel.SetActive(false);Debug.Log("已經在大廳中");}}/// <summary>/// 創建或加入房間按鈕/// </summary>public void joinOrCreateRoomBtn(){if(RoomnameInputField.text.Length<=2){return;}LobbyPanel.SetActive(false);RoomOptions roomOptions = new RoomOptions { MaxPlayers = 4 };//房間最大人數4人PhotonNetwork.JoinOrCreateRoom(RoomnameInputField.text, roomOptions, default);RoomPanel.SetActive(true);}#endregion#region Photon函數public override void OnJoinedRoom(){if (PhotonNetwork.LocalPlayer.IsMasterClient)//判斷是否是房主,是就顯示開始游戲按鈕,不是就顯示準備按鈕{readyBtn.SetActive(false);startBtn.SetActive(true);}else{readyBtn.SetActive(true);startBtn.SetActive(false);}}/// <summary>/// 當成功連接該服務器/// </summary>public override void OnConnectedToMaster(){NamePanel.SetActive(true);//顯示名字面板StartInitPanel.SetActive(false);//隱藏開始初始化面板PhotonNetwork.JoinLobby();//加入大廳Debug.Log("加入大廳成功");}#endregion }

7.新建一個RoomManagerList的空物體,同理新建一個RoomMnaager腳本,主要用來管理房間列表的顯示:

using Photon.Pun; using Photon.Realtime; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;public class RoomManager : MonoBehaviourPunCallbacks {public GameObject roomNamePrefab;//房間顯示的預制體public Transform gridLayout;//預制體的父物體/// <summary>/// 房間更新的函數,每次房間消失或者增加,就會進行調用,所以要對消失的時候進行特殊處理/// </summary>/// <param name="roomList">返回的房間參數</param>public override void OnRoomListUpdate(List<RoomInfo> roomList){Debug.Log("roomlist:" + roomList.Count);for (int i = 0; i < gridLayout.childCount; i++)//遍歷父物體下的子物體{if (gridLayout.GetChild(i).gameObject.GetComponentInChildren<Text>().text == roomList[i].Name)//有相同的物體{Destroy(gridLayout.GetChild(i).gameObject);//銷毀if (roomList[i].PlayerCount == 0)//如果房間玩家為0{roomList.Remove(roomList[i]);//移除該房間}}}foreach (var room in roomList)//遍歷生成房間的顯示{GameObject newRoom = Instantiate(roomNamePrefab, gridLayout.position, Quaternion.identity, gridLayout);//生成房間按鈕newRoom.GetComponent<RoomBtn>().roomName = room.Name;//設置房間名字newRoom.GetComponentInChildren<Text>().text = room.Name + "(" + room.PlayerCount + "/4)";//顯示參數}} }

8.為了點擊房間按鈕,可以進入該房間,所以給按鈕添加腳本事件,新建一個腳本RoomBtn,房間按鈕是一個預制體,需要事先進行設置,在scroll view里面的content下新建按鈕,然后記得給content添加Vertical layout group和content size fitter組件,同理在玩家面板,也需要設計玩家對應的預制體,方法類似,代碼如下:

using Photon.Pun; using Photon.Realtime; using System.Collections; using System.Collections.Generic; using UnityEngine;public class RoomBtn : MonoBehaviourPunCallbacks {public string roomName;void Start(){}/// <summary>/// 點擊按鈕,加入該房間/// </summary>public void JoinRoomBtn(){PhotonNetwork.JoinRoom(roomName);//加入房間NetworkManager._instance.RoomPanel.SetActive(true);//顯示房間面板NetworkManager._instance.LobbyPanel.SetActive(false);//隱藏大廳面板}}

9.在進入房間后,需要對玩家進行更新,同時要判斷是不是房主,如果是,房主則可以進行開始游戲,如果不是,則顯示一個準備按鈕。這里其實也可以做一個聊天的聯機,添加以下組件,作為聊天的輸入和顯示。

腳本InRoom代碼:

using Photon.Pun; using Photon.Realtime; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;public class InRoom : MonoBehaviourPunCallbacks {public GameObject playerInfoPrefab;//玩家按鈕預制體public Transform conlayout;//父物體List<GameObject> mplayers = new List<GameObject>();Player[] allplayers;bool ready = false;public InputField contentInput;//聊天輸入框public GameObject textPrefab;//文本預制體public Transform layoutContent;//父物體void Start(){}/// <summary>/// 當加入房間時/// </summary>public override void OnJoinedRoom(){allplayers = PhotonNetwork.PlayerList;foreach (var item in allplayers){GameObject obj = Instantiate(playerInfoPrefab, conlayout);m_PlayerInfo _PlayerInfo = obj.GetComponent<m_PlayerInfo>();_PlayerInfo.playerName = item.NickName;obj.GetComponentInChildren<Text>().text = item.NickName + "(" + "未準備" + ")";mplayers.Add(obj);}}/// <summary>/// 當有玩家進入時,更新玩家列表/// </summary>/// <param name="newPlayer"></param>public override void OnPlayerEnteredRoom(Player newPlayer){GameObject obj = Instantiate(playerInfoPrefab, conlayout);m_PlayerInfo _PlayerInfo = obj.GetComponent<m_PlayerInfo>();_PlayerInfo.playerName = newPlayer.NickName;obj.GetComponentInChildren<Text>().text = newPlayer.NickName+"("+"未準備"+")";mplayers.Add(obj);}/// <summary>/// 當有玩家離開時,更新玩家列表/// </summary>/// <param name="otherPlayer"></param>public override void OnPlayerLeftRoom(Player otherPlayer){foreach (var item in mplayers){if (item.GetComponentInChildren<Text>().text.Contains(otherPlayer.NickName)){Destroy(item);break;}}}/// <summary>/// 當離開房間時,如果房間內還有人,則設置其他人為房主/// </summary>public override void OnLeftRoom(){foreach (var item in mplayers){if (item.GetComponentInChildren<Text>().text.Contains(PhotonNetwork.LocalPlayer.NickName)){if (PhotonNetwork.LocalPlayer.IsMasterClient){foreach (var p in allplayers){if (p != PhotonNetwork.LocalPlayer){PhotonNetwork.CurrentRoom.SetMasterClient(p);break;}}}Destroy(item);break;}}}Dictionary<string, bool> IsPlayerReady = new Dictionary<string, bool>();//使用字典來進行數據廣播,廣播字典/// <summary>/// 準備按鈕事件/// </summary>public void SetReadyBtn(){foreach (var item in mplayers){m_PlayerInfo playerinfo = item.GetComponent<m_PlayerInfo>();if (!IsPlayerReady.ContainsKey(playerinfo.playerName)){IsPlayerReady.Add(playerinfo.playerName, false);}}ready = !ready;foreach (var item in IsPlayerReady){if(item.Key== PhotonNetwork.LocalPlayer.NickName){IsPlayerReady[item.Key] = ready;break;}}photonView.RPC("ReadyBtn", RpcTarget.All,PhotonNetwork.LocalPlayer.NickName,IsPlayerReady);}[PunRPC]void ReadyBtn(string xname,Dictionary<string,bool> keyValuePairs){foreach (var item in keyValuePairs){if(item.Value==true){foreach (var p in mplayers){if(p.GetComponentInChildren<Text>().text.Contains(item.Key)){p.GetComponentInChildren<Text>().text = item.Key + "(" + "已準備" + ")";break;}}}else{foreach (var p in mplayers){if (p.GetComponentInChildren<Text>().text.Contains(item.Key)){p.GetComponentInChildren<Text>().text = item.Key + "(" + "未準備" + ")";break;}}}}//foreach (var item in mplayers)//{// Debug.Log(item.GetComponentInChildren<Text>().text);// if (item.GetComponentInChildren<Text>().text.Contains(xname))// {// if(ready)// {// item.GetComponentInChildren<Text>().text= xname + "(" + "已準備" + ")";// }// else// {// item.GetComponentInChildren<Text>().text = xname + "(" + "未準備" + ")";// }// break;// }//}}//發送消息public void SendMessInfoBtn(){string info = PhotonNetwork.LocalPlayer.NickName + " :" + contentInput.text;photonView.RPC("SendMess", RpcTarget.All,info);}[PunRPC]void SendMess(string mess){GameObject textobj = Instantiate(textPrefab, layoutContent);textobj.GetComponentInChildren<Text>().text = mess;}//開始游戲public void StartGameButton(){photonView.RPC("LoadGameScene", RpcTarget.All);}[PunRPC]void LoadGameScene(){PhotonNetwork.LoadLevel(1);} }

這里還添加了一個代碼,綁定給玩家的按鈕,

代碼內容:

using System.Collections; using System.Collections.Generic; using UnityEngine;public class m_PlayerInfo : MonoBehaviour {public string playerName;}

10.新建一個場景,記得添加在build setting里面。在這個場景中,搭一個簡單的地面,同時新建一個膠囊體,作為玩家的預制體Player。添加以下組件,將他拖到以下的文件夾中,刪除場景中的Player:


11.新建一個腳本,命名為GameManager,主要是用來生成玩家,記得在場景中添加,代碼如下:

using Photon.Pun; using Photon.Realtime; using System.Collections; using System.Collections.Generic; using UnityEngine;public class GameManager : MonoBehaviourPunCallbacks {public static GameManager _insatnce;// Start is called before the first frame updatevoid Awake(){_insatnce = this;int index = 0;Player[] players = PhotonNetwork.PlayerList;foreach (var item in players){if (item.NickName == PhotonNetwork.NickName){index = item.ActorNumber - 1;// PhotonNetwork.Instantiate("Player", m_spawns.mySpawns[index].spawnPos.position, Quaternion.identity);PhotonNetwork.Instantiate("Player", Vector3.zero, Quaternion.identity);Debug.Log("userid:" + item.ActorNumber);}}} }

12.新建mPlayer腳本,用來控制玩家移動

using Photon.Pun; using System.Collections; using System.Collections.Generic; using UnityEngine;public class mPlayer : MonoBehaviourPunCallbacks {void Update(){if (photonView.IsMine){MoveController();}}public void MoveController(){float h = Input.GetAxis("Horizontal");float v = Input.GetAxis("Vertical");transform.Translate(new Vector3(h, 0, v) * 10 * Time.deltaTime);} }

13.這樣,一個基礎的聯機機制的小demo就完成了。其實整體來說,photon這套聯機機制,入門很簡單,但是后期拓展和優化需要花點時間。

最后是項目源碼:源碼地址

總結

以上是生活随笔為你收集整理的使用Photon PUN创建简单对战游戏的全部內容,希望文章能夠幫你解決所遇到的問題。

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