1. 建立NetWorkManager 空對象管理聯網
建立一個場景,場景下挂載一個空的對象NetWorkManager,為其添加NetWorkManager 和 NetworkManagerHUD 元件
2. 添加Player 對象
- 添加一個Player 對象 并将其生成為預制體Prefab
- 挂載PlayerController 腳本 控制對象的旋轉和移動
3. 實作用戶端和服務端對象同步
- 加載預制體後發現服務端和用戶端的兩個player同時在移動。解決方案:将playercontroller 繼承 NetworkBehaviour, 其中有一個isLocalPlayer 屬性,如果不是本地player就不做任何操作return.
- 同步兩邊的位置:在player中挂載NetworkTransform,就能實作同步功能
4. 給本地對象改變顔色
public override void OnStartLocalPlayer()
{
//隻在本地對象初始化完成後調用
GetComponent<MeshRenderer>().material.color = Color.blue;
}
5. 控制主角的射擊
按下空格鍵 發出子彈
private void fire()
{
GameObject bullet = Instantiate(bulletPrefab, bulletPos);
bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 10f;
Destroy(bullet, 2);
}
6. 子彈同步到用戶端
- 首先在NetWorkManager 中添加 需要生成的子彈
- 所有的子彈都需要是服務端生成,然後同步到各個用戶端。在生成子彈的fire方法前加上【Command】然後方法名更改為CmdFire(),表示這個方法是在服務端調用。
- 給bullet子彈對象添加NetWorkTransform ,同步子彈
[Command]
private void CmdFire()
{
GameObject bullet = Instantiate(bulletPrefab, bulletPos);
bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 10f;
Destroy(bullet, 2);
//同步到各個用戶端
NetworkServer.Spawn(bullet);
}
7. 給Player添加血條顯示
- 建立Slider
- Slider 的Canvas 加上LookAtCamera 腳本,防止血條跟随Player旋轉
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LookAtCamera : MonoBehaviour
{
void Update()
{
transform.LookAt(Camera.main.transform);
}
}
- 編寫Health邏輯 使其與slider資料綁定
public class Health : MonoBehaviour
{
// 固定血量
public int bloodCount = 100;
public int allBlood = 100;
public Slider slider;
public void takeDemage()
{
//受到傷害
if (bloodCount > 0)
{
bloodCount -= 10;
slider.value = bloodCount / (float)allBlood;
}
}
}
8. 同步血條和血量
比較坑的一點是,你會發現上面第7步做完後,服務端的血量一直在掉,然而用戶端的血量要麼不掉,要麼掉的很少。這是因為咱們的開火邏輯是服務端在處理,由于網絡和傳輸的問題,不管怎麼樣服務端執行的一定要比用戶端快,當服務端的碰撞完了後銷毀了這個對象,用戶端就沒有這個對象了,進而不能時效的進行碰撞檢測,減少血量。
解決方法:血量減少的邏輯也讓其隻在服務端處理,用戶端同樣隻做同步操作。
public class Health : NetworkBehaviour
{
// 同步血量
[SyncVar(hook ="OnChangeHealth")]
public int bloodCount = 100;
public int allBlood = 100;
public Slider slider;
public void takeDemage()
{
if (!isServer) return;
//受到傷害
if (bloodCount > 0)
{
bloodCount -= 10;
}
}
//檢測到SncVar 标準的變量變化後,就會執行 OnChangeHealth 這個方法
void OnChangeHealth(int health)
{
slider.value = bloodCount / (float)allBlood;
}
}