本篇使用的是5.3版後有UNET的UNITY
目標:基本連線遊戲機制+陣亡後延遲重生
1.延續前篇(UNET連線遊戲(六){你快掛囉,HUD_UI續})
已經有血條的控制與顯示後,接下來針對陣亡的玩家做一些對應的控制,例如:
- 不能再發射子彈
- 不能繼續移動
- 停留數秒後才重生
- 畫面變紅的陣亡提示
- 以及模擬暈眩
2.以上行為可以改寫之前的DamageScript.cs來達成對陣亡人物的行動限制,不能發射子彈的部分可以透過關閉GunController腳本達成(把槍的零件關閉),不能移動則透過關閉FirstPersonController fpsController腳本達成,畫面變紅則需要Image的UI。
using UnityStandardAssets.Characters.FirstPerson; GunController gunCtrl; FirstPersonController fpsController; Image DEAD_BG;
增加上列的引用和宣告,並於Start()處取得相關零件,如下
gunCtrl = GetComponent<GunController> (); fpsController = GetComponent<FirstPersonController> (); DEAD_BG = GameObject.Find ("BG").GetComponent<Image> ();
3.為了統一將發射子彈與移動關閉,我們新增一個帶有bool引數的Alive方法作為檢驗
void Alive(bool b){ gunCtrl.enabled = b; fpsController.enabled = b; }
接下來就可以使用Alive (false); 或 Alive (true);關閉或打開角色控制
4.重生延遲5秒會用到Invoke 配合Go()方法達成,如下:
[ClientRpc] void RpcRebirth(){ Invoke ("Go",5.0f); print ("DIE"); if (isLocalPlayer)Alive (false); } void Go(){ HP = HP_MAX; if (isLocalPlayer) { Transform spawn = NetworkManager.singleton.GetStartPosition(); transform.position = spawn.position; Alive (true); } }
把原來重置玩家的功能包入方法後,同時回滿HP
5.以上已經可以限制陣亡角色的行動,但畫面見漸漸變紅的功能必須透過新增UI執行,製作全版紅色UI命名BG然後預設透明
6.撰寫一個死亡時要執行的void Dead(),並使用InvokeRepeating於Alive()內反覆執行,直到5秒Invoke呼叫Go方法後CancelInvoke (“Dead”)取消Invoke的功能,內容如下
void Alive(bool b){ gunCtrl.enabled = b; fpsCtrl.enabled = b; charCtrl.enabled = b; rotaSpeed = 270; InvokeRepeating ("Dead",0.1f,0.02f); } void Dead (){ transform.Rotate(Vector3.right * Time.deltaTime * -30); transform.Rotate(Vector3.up * Time.deltaTime * rotaSpeed); rotaSpeed-=2; DEAD_BG.color += new Color (0, 0, 0, 0.003f); }
transform.Rotate 用來模擬暈眩並且漸漸降低旋轉速度,以及提高UI的不透明度
7.完整的DamageScript.cs
using UnityEngine; using System.Collections; using UnityEngine.Networking; using UnityEngine.UI; using UnityStandardAssets.Characters.FirstPerson; public class DamageScript : NetworkBehaviour { AudioSource damageAudio; GunController gunCtrl; FirstPersonController fpsCtrl; CharacterController charCtrl; public Image HP_BAR; public Image DEAD_BG; public const int HP_MAX = 3; int rotaSpeed; [SyncVar(hook = "HpBar")]public int HP = HP_MAX; void Awake() { } void Start (){ damageAudio = GetComponent<AudioSource>(); gunCtrl = GetComponent<GunController> (); fpsCtrl = GetComponent<FirstPersonController> (); charCtrl = GetComponent<CharacterController> (); DEAD_BG = GameObject.Find ("BG").GetComponent<Image> (); } public void TakeDamage(int D){ if (!isServer) { return; } if (HP > 0) { HP -= D; if(HP <= 0)RpcRebirth (); } } void HpBar(int h){ print (h); if(HP_BAR)HP_BAR.fillAmount = (float)h / (float)HP_MAX; } void Alive(bool b){ gunCtrl.enabled = b; fpsCtrl.enabled = b; charCtrl.enabled = b; rotaSpeed = 270; InvokeRepeating ("Dead",0.1f,0.02f); } void Dead (){ transform.Rotate(Vector3.right * Time.deltaTime * -30); transform.Rotate(Vector3.up * Time.deltaTime * rotaSpeed); rotaSpeed-=2; DEAD_BG.color += new Color (0, 0, 0, 0.003f); } [ClientRpc] void RpcRebirth(){ Invoke ("Go",5.0f); print ("DIE"); if (isLocalPlayer)Alive (false); } void Go(){ HP = HP_MAX; if (isLocalPlayer) { DEAD_BG.color = new Color (1, 0, 0, 0); Transform spawn = NetworkManager.singleton.GetStartPosition(); transform.position = spawn.position; Alive (true); CancelInvoke ("Dead"); } } }