PUN ☀️九、玩家网络实例化与昵称显示
文章目錄
- 🟥 目標
- 1?? 玩家網絡實例化
- 2?? 實現戰斗數據不重置
- 3?? 位置重置
- 4?? 激光碰撞判斷
- 🟧 代碼編寫
- 🚩 PlayerManager
- 🚩 GameManager
- 🟨 血條、昵稱顯示
- 🟩 最終效果展示:
🟥 目標
1?? 玩家網絡實例化
即把玩家要操控的角色生成出來。GameManager里面Start時實例化角色。
2?? 實現戰斗數據不重置
原先只有兩個人,再加入一個人,會切換到3人的場景。但原先的兩個人當前戰斗數據會被重置,這是不合理的。
我們來讓之前的玩家數據不被重置。
a、PlayerManager 聲明的靜態字段LocalPlayerInstance 記錄本地玩家實例化的。
Awake賦值,并在加載新場景時,不銷毀當前角色。
b、但在重新加載新場景時,GameManager 腳本 Start時會再次實例化角色,于是一個玩家就有了兩個角色。所以GameManager Start時根據判斷 LocalPlayerInstance 是否為空,確定是否已經實例化了角色。
3?? 位置重置
若從3人房切換到2人房,房間變小了。若切換后原先在地面上的角色懸空了,會出Bug。
所以增加判斷:若切換后沒踩在地板上,則位置回到出生位置(原點高空)。
方法:PlayerManager 腳本Start時增加加載完場景時的委托,增加的委托事件判斷當前角色位置
4?? 激光碰撞判斷
解決當跳躍時觸發激光,會造成自身減血的現象。
這是因為激光與自身角色控制器的觸發器檢測碰撞了,我們要檢測激光不是接觸的自身才行,避免自己碰撞掉血。解決辦法:
- 設置自身的Tag,觸發檢測Tag再決定是否減血。
- PlayerManager腳本判斷射線碰撞到的角色是否是自己,不是的話再減血(此處采用)
現在我們可以測試看看,如果發現連接不上,就換成中國區Appid試試,我隔了一天申請通過了,現在你申請的應該也好了。
🟧 代碼編寫
🚩 PlayerManager
using UnityEngine; using Photon.Pun;public class PlayerManager : MonoBehaviourPunCallbacks, IPunObservable {#region Parameterspublic GameObject beams;//記錄本地玩家實例化public static GameObject LocalPlayerInstance;public float Health = 1f;//當用戶開火時,為Truebool IsFiring;#endregion#region Mono CallBacksvoid Awake(){beams.SetActive(false);if (PhotonNetwork.IsConnected == true && photonView.IsMine)LocalPlayerInstance = gameObject;DontDestroyOnLoad(gameObject);}void Start(){//當重新加載場景時,檢測改腳本所賦值的角色是否踩在空中,若是,則回到出生點重新降落。UnityEngine.SceneManagement.SceneManager.sceneLoaded += OnSceneLoaded;if (PhotonNetwork.IsConnected && photonView.IsMine)GetComponent<Skode_CameraWork>().OnStartFollowing();}void Update(){if (Health <= 0f)GameManager.ins.Skode_LeaveRoom();if (PhotonNetwork.IsConnected == true && photonView.IsMine)ProcessInputs();if (IsFiring != beams.activeSelf)beams.SetActive(IsFiring);}void OnTriggerEnter(Collider other){if (!photonView.IsMine && !other.CompareTag("beam"))return;Health -= 0.1f;}void OnTriggerStay(Collider other){if (!photonView.IsMine && !other.CompareTag("beam"))return;//乘以增量時間,防止因為幀率FPS不同,扣血不同(舉例:不乘,每幀執行一次扣血,卡的人比流暢的人扣血少)Health -= 0.1f * Time.deltaTime;}#endregion#region PUN CallBackspublic override void OnDisable(){base.OnDisable();UnityEngine.SceneManagement.SceneManager.sceneLoaded -= OnSceneLoaded;}public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info){if (stream.IsWriting){// 我們擁有這個角色:把我們的數據發送給其他人stream.SendNext(IsFiring);stream.SendNext(Health);}else{// 網絡角色,接收數據IsFiring = (bool)stream.ReceiveNext();Health = (float)stream.ReceiveNext();}}#endregion#region Private Methodsvoid OnSceneLoaded(UnityEngine.SceneManagement.Scene scene, UnityEngine.SceneManagement.LoadSceneMode loadingMode){CalledOnLevelWasLoaded(scene.buildIndex);}void CalledOnLevelWasLoaded(int level){// 檢查我們是否在競技場外面,如果是這樣,移動到競技場中心的安全地帶if (!Physics.Raycast(transform.position, -Vector3.up, 5f)){transform.position = new Vector3(0f, 5f, 0f);}}void ProcessInputs(){//鼠標左鍵if (Input.GetButtonDown("Fire1"))IsFiring = true;if (Input.GetButtonUp("Fire1"))IsFiring = false;}#endregion }🚩 GameManager
using UnityEngine.SceneManagement; using Photon.Pun; using Photon.Realtime; using UnityEngine;public class GameManager : MonoBehaviourPunCallbacks {public static GameManager ins;[Tooltip("用來代表玩家的預置體")]public GameObject playerPrefab;#region Mono CallBacksprivate void Awake(){ins = this;}private void Start(){//若本地玩家第一次進游戲場景,還未生成角色,則生成一個。//且這個角色通過使用PhotonNetwork.Instantiate進行同步if (PlayerManager.LocalPlayerInstance == null)PhotonNetwork.Instantiate(playerPrefab.name, new Vector3(0f, 5f, 0f), Quaternion.identity, 0);}#endregion#region Public Methods//離開服務器房間Btnpublic void Skode_LeaveRoom(){//不允許主客戶端離開房間if (!PhotonNetwork.IsMasterClient)PhotonNetwork.LeaveRoom();}#endregion#region PUN Callbacks/// <summary>/// 本地玩家離開服務器房間時回調/// </summary>public override void OnLeftRoom(){// 加載大廳場景SceneManager.LoadScene(0);}/// <summary>/// 其他玩家連接房間時的回調(不是自己)/// </summary>public override void OnPlayerEnteredRoom(Player other){print(other.NickName + " 加入房間");//根據當前玩家的人數,主客戶端加載對應場景if (PhotonNetwork.IsMasterClient)LoadArena();}//當玩家離開房間或變得不活動時調用。public override void OnPlayerLeftRoom(Player other){print(other.NickName + " 離開了房間");//根據當前玩家的人數,主客戶端加載對應場景if (PhotonNetwork.IsMasterClient)LoadArena();}#endregion#region Private Methodsvoid LoadArena(){//Photon分為主客戶端、其他客戶端。只有主客戶端才可進行加載房間。//根據當前房間人數加載對應場景。該方法會使其他玩家會自動加入主客戶端的房間PhotonNetwork.LoadLevel("Room for " + PhotonNetwork.CurrentRoom.PlayerCount);}#endregion }🟨 血條、昵稱顯示
1、創建UI
在人物下創建3D Slider血條,并且有文本框用于顯示名字。
若是滑動條即使是滿值也不到頭,只需改下滑動條下Fill Area 的 Right值就好了。
2、代碼賦值
將下代碼掛到機器人身上,并賦值。
using UnityEngine; using UnityEngine.UI;public class PlayerUI : MonoBehaviour {#region Parameters[Tooltip("顯示玩家名字的UI文本")]public Text playerNameText;[Tooltip("健康值Slider")]public Slider playerHealthSlider;[Tooltip("用于獲取生命值賦值給血條")]public PlayerManager target;#endregion#region Mono Callbacksvoid Start(){playerNameText.text = target.photonView.Owner.NickName;}void Update(){playerHealthSlider.value = target.Health;}#endregion }若現在還沒把機器人放到 Resources里,現在就要放進去了。已經放進去的Apply一下。
將 Resources 里的機器人預制體賦值給GameManager,刪掉面板的機器人。
各個場景的 GameManager都賦值一下,接下來要進行測試了。
還有,記得關閉離線模式哦
🟩 最終效果展示:
落頭上了哈哈
好啦,本系列暫告一段落🧸
大家還有什么問題,歡迎在下方留言!
如果你有 技術的問題 或 項目開發
都可以加下方聯系方式
和我聊一聊你的故事🧡
總結
以上是生活随笔為你收集整理的PUN ☀️九、玩家网络实例化与昵称显示的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Docker容器镜像加速器
- 下一篇: Hadoop加速器GridGain