首先添加兩個組件
運行后我們可以發現大致的聯機已經完成
多人聯機我們在玩家游戲對象上添加兩個組件。
玩家移動
然后我們再添加一個移動的腳本,寫入代碼。
using UnityEngine.Networking;
public class PleyerController : NetworkBehaviour {
// Update is called once per frame
void Update () {
if (isLocalPlayer==false) {//如果不是本地的
return;//不執行移動的代碼
}
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
transform.Rotate(Vector3.up*h*120*Time.deltaTime);
transform.Translate(-Vector3.forward * v * 3 * Time.deltaTime);
}
最后我們打包出來測試下,我們把Unity當作服務器和客戶端,把打包出來的當做客戶端.我們可以發現這樣就已經連接上了。因為都是本地IP所以沒有設置IP地址。端口號是系統默認的端口7777。
區分敵我
下面我們再來看看怎么區分敵我,附上代碼
// <summary>
/// 這個方法區分敵我,自身玩家設置為藍色,敵人是白色.
/// </summary>
public override void OnStartLocalPlayer()
{
//這個方法只會在本地角色那里調用,當角色被創建的時候
GetComponent<MeshRenderer>().material.color = Color.blue;
}
發射子彈
首先我們在子彈的預制物上加上Network Identity組件,并且將生成的子彈上傳到網絡上。
下面我們來讓我們的游戲對象擁有射擊功能,看看怎么做吧,先附上射擊的代碼。這個CmdFire()方法我們在玩家Player預制物的Update里面調用
public GameObject BulletPrefab;
public Transform bulletSpawe;
private float BulltSpeed = 2000f;
[Command]//表示雖然客戶端調用這個方法,但是運行是在服務端運行.
void CmdFire()
{//命名必須Cmd開頭
GameObject bullet = Instantiate(BulletPrefab, bulletSpawe.position, bulletSpawe.rotation);
bullet.GetComponent<Rigidbody>().velocity = -bullet.transform.forward * BulltSpeed * Time.deltaTime;
Destroy(bullet, 2f);
NetworkServer.Spawn(bullet);//生成指定的物體同步到各個客戶端
}
隨后我們又發現子彈是同步了,但是子彈的速度沒有同步過來,So我們將NetworkTransform組件也加上來,NetworkTransform不僅能同步Transform還能同步Rigibody.
這下我們可以發現子彈都已經同步上了。
控制UI血量值同步
當你添加血量減少受到傷害的方法后你會發現服務端和客戶端的血量值并不是同步的,那么是為什么呢,這是因為服務器端在發射子彈后敵人的血量在減少同時子彈也被銷毀了,那么客戶端就有可能無法同時受到傷害因為在服務器端子彈已經被銷毀了,那么我們如何去實現同步能,這里我們只能讓子彈傷害在服務端去運行然后在同步到所有的客戶端。下面我們附上代碼.將這個血量的腳本掛載在Player游戲對象上.
using UnityEngine.Networking;
public class Health : NetworkBehaviour {
public Slider HealthSlider;
public const int MaxHealth = 100;
[SyncVar (hook ="OnChangeHealth")]//同步變量,表示這個變量同步到各個客戶端
public int curentllealth = MaxHealth;
//血量減少的方法,受到傷害
public void TakeDamage(int damage) {
if (isServer == false) return;//血量的處理只在服務器端執行
curentllealth -= damage;
if (curentllealth<=0) {
curentllealth = 0;
Debug.Log("Death");
}
}
void OnChangeHealth(int health) {
HealthSlider.value = health / (float)MaxHealth;
}
}
然后我們在創建一個腳本這個腳本掛載在我們的子彈上,里面寫入它的碰撞方法。
public class Bullet : MonoBehaviour {
private void OnCollisionEnter(Collision collision)
{
if (collision.transform.tag=="Player") {
GameObject hit = collision.gameObject;
Health health = hit.GetComponent<Health>();
if(health!=null){
health.TakeDamage(20);
}
Destroy(this.gameObject);
}
}
}
這樣我們就同步了血量傷害的減少
重生到隨機的某幾個位置
首先我們先隨便創建一個位置點空物體。在其上面添加組件Network Start Position。這個是在服務器開始的時候指定一個位置,然后我們在多創建一個位置同意添加這個組件。讓我們的玩家在這兩個位置隨機生成。
然后我們將Player Spawn Met的參數設置為Round Robin指輪流在這兩個位置轉換.
private NetworkStartPosition[] SpawnPosition;
void Start() {
if (isLocalPlayer) {
SpawnPosition = FindObjectsOfType<NetworkStartPosition>();
}
}
//重生
[ClientRpc]//客戶端遠程調用
void Rpcespawn() {//命名必須Rpc開頭
if (isLocalPlayer==false) {
return;
}
Vector3 spawnposition = Vector3.zero;
if (SpawnPosition!=null&& SpawnPosition.Length>0) {
spawnposition = SpawnPosition[Random.Range(0, SpawnPosition.Length)].transform.position;
}
transform.position = spawnposition;
}
然后我們將重生的方法調用到血量小于等于0的時候
敵人的隨機生成
using UnityEngine.Networking;
public class EnumSpwen : NetworkBehaviour {
public GameObject Onemyprefab;
public int numberOfEnemies;
//會在服務器啟動的時候調用
public override void OnStartServer()
{
for (int i=0;i< numberOfEnemies;i++) {
Vector3 position = new Vector3(Random.Range(-6f, 6f), 0f,Random.Range(-6f,6f));
Quaternion rotation = Quaternion.Euler(0, Random.Range(0, 360), 0);
GameObject enemy = Instantiate(Onemyprefab,position,rotation);
NetworkServer.Spawn(enemy);
}
}