玩家的血量狀態在伺服器上做變化,之後再讓這些更動給所有用戶端,這稱作伺服器權限(Server Authority),更多關於伺服器權限的資訊可以點這裡。
為了讓我們的目前血量和傷害系統能夠在伺服器權限下運作,需要使用SyncVars這個特殊變數,讓各個數值可以同步於網路環境。此變數在腳本中寫做[SyncVar],更多關於SyncVars的資訊可以點這裡。
首先開啟Health腳本,修改成以下內容,新增命名空間UnityEngine.Networking,把繼承改成NetworkBehaviour,在currentHealth前加上[SyncVar],最後增加if (!isServer)判斷式讓TakeDamage函式只會在伺服器上執行:
using UnityEngine; using UnityEngine.UI; using UnityEngine.Networking; using System.Collections; public class Health : NetworkBehaviour { public const int maxHealth = 100; [SyncVar] public int currentHealth = maxHealth; public RectTransform healthBar; public void TakeDamage(int amount) { if (!isServer) { return; } currentHealth -= amount; if (currentHealth <= 0) { currentHealth = 0; Debug.Log("Dead!"); } healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y); } }編譯後可以進行測試,測試連線時結果的方法點我。
現在我們完成本文開頭提到的;在伺服器上做血量變化,在隨後同步給用戶端。
在但是同步的結果很難讓所有用戶端看到,這是因為healthBar目前只在伺服器上做數值改變,並不適用其他用戶端。現在使用者可以在Inspector介面中看到當前血量currentHealth的數值,接著我們要讓healthBar的顯示結果正確,必須同步Foreground物件的RectTransform數值。
現在我們要使用另一種狀態同步變數;SyncVar hook。
SyncVar hook能把一個函式連接到SyncVar,當被設成SyncVar的變數發生數值改變時,就會在伺服器與所有用戶端上呼叫該函式,關於SyncVar hook的更多資訊可以看這裡。
開啟Health腳本,修改以下內容,將原本在TakeDamage做的healthBar.sizeDelta數值修改,調整到OnChangeHealth中執行,並使用[SyncVar(hook = "OnChangeHealth")]讓此函數在currentHealth發生變化時被呼叫,另外要注意的是,呼叫時currentHealth會傳入該函數,所以變數類型必須相同:
using UnityEngine; using UnityEngine.UI; using UnityEngine.Networking; using System.Collections; public class Health : NetworkBehaviour { public const int maxHealth = 100; [SyncVar(hook = "OnChangeHealth")] public int currentHealth = maxHealth; public RectTransform healthBar; public void TakeDamage(int amount) { if (!isServer) { return; } currentHealth -= amount; if (currentHealth <= 0) { currentHealth = 0; Debug.Log("Dead!"); } } void OnChangeHealth (int currentHealth) { healthBar.sizeDelta = new Vector2(health, currentHealth.sizeDelta.y); } }編譯後可以進行測試,測試連線時結果的方法點我。
現在Healthbar在所有用戶端上應該是同步的,下一篇我們要做的是死亡判斷及重生。
上一篇:玩家血量(單機)
下一篇:死亡和重生
建立一個簡單的多人連線範例
void OnChangeHealth(int currentHealth)
回覆刪除{
healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
}