本篇使用的是5.3版後有UNET的UNITY
目標:基本連線遊戲機制+敵方玩家血條(UI)
1.延續前篇(UNET連線遊戲(四){我快死了,HP_UI})
- 隨後在玩家身上掛載一隻程式PlayerID.cs
using UnityEngine; using System.Collections; using UnityEngine.Networking; using UnityEngine.UI; public class PlayerID : NetworkBehaviour { void Start () { GetNetIdentity (); } // Update is called once per frame void Update () { } void GetNetIdentity(){ this.gameObject.name = "PLAYER_" + GetComponent<NetworkIdentity> ().netId.ToString(); if (isLocalPlayer) { GameObject player = GameObject.Find ("PLAYER_ID"); player.GetComponent<Text> ().text = ID (); } } public string ID(){ return this.gameObject.name; } }
透過GetNetIdentity()的功能去取得每個PLAER在網路上獨一的netId,那通常是一個流水號,所以透過this.gameObject.name = “PLAYER_” +這個流水號重新命名這個PLAYER,以便我們之後識別其他玩家。
- 物件確實被重新命名後接下來就需要在畫面上顯示,這部分一樣透過UGUI來呈現。比較不同的是這個UI要動態產生;因此我們先從畫面上編輯再將它製成預製物件。
效果預覽:
- 這個UI由兩個部分組成:血條(命名為HP_ENEMY)+ID文字(命名為ID)
這個血條跟製作自己的HP一樣的方式只是要的是比較小的版本。先在HUD的UI畫布下加入一個Image並放入1PX的白點,(做法可以參考前篇),需求若為長寬10:1的BAR可以先依照下圖的參數設定
- 子物件加入一個Text的UI,並寫以左下角對其的方式貼齊血條。參數設定可以參考下圖
把HP_ENEMY拖入Resources資料夾製成預製物,刪除場景上的HP_ENEMY - 接下來需要的就是人物進場時,要將這個物建置入HUD內
跟之前的GunController.cs生成子彈一樣的方式來生成這個血條,差別在這個血條是由非玩家的人物產生,我們撰寫一條EnemyHP.cs來控制他using UnityEngine; using System.Collections; using UnityEngine.Networking; using UnityEngine.UI; public class EnemyHP : NetworkBehaviour { private GameObject HudBar; // Use this for initialization void Start () { if(!isLocalPlayer)SpawnHpBar (); } // Update is called once per frame void Update () { } void SpawnHpBar () { HudBar = Instantiate (Resources.Load ("HP_ENEMY")) as GameObject; HudBar.name = "PLAYER_" + GetComponent<NetworkIdentity>().netId.ToString(); HudBar.transform.parent = GameObject.Find ("HUD").transform; HudBar.GetComponent<UIReset> ().playerName = this.gameObject; } }
- 執行後發現跟我們原來的設計不太相同,雖然所屬UI跟著PLAYER改變名子了但在畫面上的位置還有大小不太正常
原因在於原來的UI物件是在HUD的子物件條件下設置的,離開場景外後參數會有所變化,所以重新置入的時候我們需手動將這些數值重置。
包括:Left、Top、Right、Bottom以及Scale的X、Y、Z縮放 - 在HP_ENEMY預製物加入一個UIReset.cs將UI歸零重置
using UnityEngine; using System.Collections; using UnityEngine.UI; public class UIReset : MonoBehaviour { RectTransform UISET; // Use this for initialization void Start () { Reset (); } // Update is called once per frame void Update () { } void Reset(){ UISET = this.transform.GetComponent<RectTransform> (); UISET.localScale = new Vector3 (1, 1, 1); UISET.offsetMin = new Vector2 (0,0); UISET.offsetMax = new Vector2 (0,0); transform.FindChild ("ID").GetComponent<Text> ().text = this.gameObject.name; } }
UISET.localScale重置縮放比為1
offsetMin、offsetMax重置XY的最小最大位置,讓UI與邊界距離為0
並透過transform.FindChild (“ID”)順手將文字替換為角色ID - 剩下的問題則是位置,目前雖然生成UI在HUD內,但他不會跟著角色人物移動,因此我們繼續強化剛剛UIReset.cs的程式,增添UIpos()方法在Update裡反覆取得人物的位置並且換算UI的正確位置。
using UnityEngine; using System.Collections; using UnityEngine.UI; public class UIReset : MonoBehaviour { RectTransform UISET; public GameObject playerName; GameObject playerCamera; Vector3 pos; Vector3 pos_scr; // Use this for initialization void Start () { Reset (); } void Update () { if (playerName) { UIpos (); } else Destroy (this.gameObject); } void Reset(){ UISET = this.transform.GetComponent<RectTransform> (); UISET.localScale = new Vector3 (1, 1, 1); UISET.offsetMin = new Vector2 (0,0); UISET.offsetMax = new Vector2 (0,0); transform.FindChild ("ID").GetComponent<Text> ().text = this.gameObject.name; playerCamera = GameObject.FindWithTag ("LocalCamera"); } void UIpos(){ pos = new Vector3 (playerName.transform.position.x , playerName.transform.position.y + playerName.GetComponent<Collider>().bounds.size.y*0.75f, playerName.transform.position.z); pos_scr = playerCamera.GetComponent<Camera>().WorldToScreenPoint (pos); //Debug.Log (pos_scr); if (pos_scr.z > 0 ) { UISET.anchorMin = new Vector2 (pos_scr.x / Screen.width - 0.05f, pos_scr.y / Screen.height - 0.01f); UISET.anchorMax = new Vector2 (pos_scr.x / Screen.width + 0.05f, pos_scr.y / Screen.height); } else { UISET.anchorMin = new Vector2 (1, 1); } } }
但是由於UI是以玩家本身的攝影機作為基準來設定的,29行用尋找物件標籤的方式找到本地玩家的攝影機,因此除了在標籤列表增加LocalCamera的標籤以外,很早之前的PlayerController.cs裡也要加上一些判斷,來幫本地玩家的攝影機掛上這個標籤,如下: 29-32的else{…}
using UnityEngine; using UnityStandardAssets.Characters.FirstPerson; using UnityEngine.Networking; public class PlayerController: NetworkBehaviour { private FirstPersonController fpsController; private Transform playerCameraTransform; private Camera playerCamera; private AudioListener playerAudioListener; void Start() { if (!isLocalPlayer) { fpsController = GetComponent<FirstPersonController> (); playerCameraTransform = transform.FindChild ("FirstPersonCharacter"); playerCamera = playerCameraTransform.GetComponent<Camera> (); playerAudioListener = playerCameraTransform.GetComponent<AudioListener> (); if (fpsController) { fpsController.enabled = false; } if (playerCamera) { playerCamera.enabled = false; } if (playerAudioListener) { playerAudioListener.enabled = false; } } else { playerCameraTransform = transform.FindChild ("FirstPersonCharacter"); playerCameraTransform.tag = "LocalCamera"; } } }
- 連線執行就可以看到對方的ID和HP跟著跑啦