章國雁
(安徽工商職業(yè)學院,安徽 合肥 231131)
目前,國內外許多學者對于利用游戲引擎進行網絡游戲開發(fā)進行了大量的研究,如劉賢梅等利用Unity引擎為平臺,采用 MVC 架構實現(xiàn)了一款ARPG類型多人在線游戲;李偉在Unity3D的基礎上與網絡通信原理相結合,采用預測式位置同步的方式減少網絡延時帶來的誤差;干建松基于Unity引擎的Unet模塊實現(xiàn)了局域網的多人聯(lián)網游戲功能;吳晶晶等基于Unity3D引擎結合協(xié)同程序技術實現(xiàn)預先式同步數據讀取,實現(xiàn)了一款MMORPG類型的網絡游戲;薛玉倩介紹了基于Unity3D的網絡游戲總體設計與實現(xiàn)程序。以上學者研究,對于網絡游戲的開發(fā)技術起到了積極的推動作用。本文在前人的研究基礎上實現(xiàn)了一款多人在線游戲開發(fā)案例。
本案例以Unity3D游戲引擎為開發(fā)平臺,實現(xiàn)一款局域網多人聯(lián)網游戲,包含服務端和客戶端。網絡功能使用游戲引擎內置的Unet系統(tǒng)進行開發(fā),該系統(tǒng)提供了NetworkManager網絡管理組件進行服務端和客戶端的創(chuàng)建,NetworkIdentity網絡標識組件進行網絡中每個物體的標識,NetworkTransform網絡傳輸組件進行網絡同步等。
導入案例資源圖片到Unity3D引擎,修改圖片類型為精靈Sprite,添加剛體組件Rigidbody2D和盒形碰撞器組件BoxCollider2D等,添加完成后創(chuàng)建為預制體。
網絡游戲涉及到服務端和客戶端的創(chuàng)建、網絡地址和端口號、網絡中各類物體包括玩家的標識、網絡同步等問題。案例采用Unet系統(tǒng)的NetworkManager組件進行游戲網絡的管理,網絡地址設置為localhost(本機),端口號為7777;在出生信息SpawnInfo一欄,注冊客戶端玩家、外星人、子彈等網絡游戲中需要進行實例化生成的物體。NetworkManagerHUD組件進行游戲服務端和客戶端創(chuàng)建的UI界面顯示。對網絡游戲中的物體添加NetworkIdentity組件進行網絡唯一標識和添加NetworkTransform組件進行網絡同步。
游戲初始界面需要生成3行10列的外星人矩陣,同時矩陣保持左右水平移動,每次到達水平邊界時,向下移動一個距離。程序設計思路為,通過定義一個動態(tài)數組來存儲外星人矩陣數據,循環(huán)語句生成外星人數據后存入動態(tài)數組。以生成第一行的外星人為例,其核心代碼如下:
public GameObject alien1Prefab;//第一種外星人預制體
public List
//服務端啟動時調用
public override void OnStartServer() {
float startx = -8; //表示在-8這個列的位置
for (int i = 0; i < 10; i++) {//循環(huán)語句實現(xiàn)外星人數據生成和存儲
CreateAlien(alien1Prefab,startx,12); //在12行的位置生成第一種外星人Alien1
startx += 1.6f; //每次偏移1.6的距離,保證alien圖標不重疊
}
}
//創(chuàng)建外星人alien函數
void CreateAlien(GameObject prefab,float posX,float posY) {
GameObject alien= Instantiate(prefab) as GameObject;//實例化一個alien
alien.transform.position = new Vector3(posX, posY, 0f);//指定位置
aliens.Add(alien); //把新生成的alien加入列表
NetworkServer.Spawn(alien); //同步生成到客戶端
}
在客戶端中,當多個玩家進行網絡游戲時,用戶只能控制當前設備上的玩家,需要對玩家的控制權限進行分離。當玩家移動過后,需要保持其他客戶端網絡同步狀態(tài)。程序思路為通過isLocalPlayer屬性值判斷是否為當前玩家,如果不是則不能進行控制;當前玩家進行移動操作后,發(fā)送一個同步命令,其核心代碼如下:
private int oldDx; //之前的玩家位置
void Update () {
if (!isLocalPlayer) return; //是否本地玩家,不是則返回,控制分離
int dx = 0;
if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A))
dx -= 1;//向左移動一個位置
if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
dx += 1; //向右移動一個位置
//當原來的值跟最新的值不一致,則說明玩家移動
if (dx != oldDx) {
CmdMove(dx); //調用移動函數
oldDx = dx; }
}
[Command]
void CmdMove(int dx) {//移動函數
if (!alive) return; //如果死亡狀態(tài),則返回
moveX = dx;
GetComponent
}
游戲實時監(jiān)控用戶的輸入指令,當用戶按下鼠標左鍵或者空格鍵時,玩家開火發(fā)射子彈,并在網絡中進行同步。其開火函數的部分代碼如下:
public GameObject bulletPrefab; //玩家的子彈預制體
[Command]
private void CmdShoot() {//開火函數
//實例化生成單個子彈物體
GameObject myBullet = (GameObject)Instantiate(bulletPrefab,
transform.position + Vector3.up, Quaternion.identity);
NetworkServer.Spawn(myBullet); //在網絡中同步生成子彈
}
由于游戲生成了3行10列的外星人矩陣,為了游戲的可玩性考慮,游戲設計時做了限制,初始狀態(tài)只允許最下面一行的外星人可以發(fā)射子彈,而上面兩行的外星人暫時不能發(fā)射子彈,當下面的外星人被銷毀時才可以發(fā)動攻擊。實現(xiàn)算法思路為,遍歷外星人動態(tài)數組的每個元素,尋找跟當前元素同一列的下一行外星人,如果能找到,則當前元素外星人不能發(fā)射子彈,如果尋找不到,則當前外星人為最下面一行,可以發(fā)射子彈。
給子彈物體增加觸發(fā)器組件,程序判斷其他物體進入子彈觸發(fā)器范圍時,則銷毀該物體,同時銷毀子彈自身。以玩家子彈為例,如果進入觸發(fā)器的是外星人,則銷毀外星人物體和子彈自身。其觸發(fā)器核心代碼如下:
void OnTriggerEnter2D(Collider2D collider) {//collider指的是碰撞的物體
AlienInvader hitAlien = collider.gameObject.GetComponent
if (hitAlien != null) {//判斷是否碰撞到了外星人
NetworkServer.Destroy(hitAlien.gameObject);//消除外星人
NetworkServer.Destroy(this.gameObject);//消除子彈自身
}
}
良好的UI界面有助于提升游戲體驗,目前業(yè)內普遍采用的UI制作工具主要有uGUI和NGUI,其中uGUI是Unity3D引擎內置的制作工具,制作方便靈活;NGUI是一款專門用于UI制作的插件,功能強大,但需要單獨進行安裝。本案例采用uGUI系統(tǒng)進行UI界面的制作,使用Canvas畫布、Text文本、Image圖像、Button按鈕等控件搭建了游戲的登錄界面和游戲的運行界面,登錄界面包含創(chuàng)建主機UI和連接主機UI,運行界面包含計分UI和生命值UI。
案例制作完成后,可以發(fā)布到本地PC端進行功能測試,如圖1所示,玩家控制已經分離,多個客戶端保持同步狀態(tài),具備局域網多人在線游戲的聯(lián)網功能,具有較好的可玩性。

圖1 多人在線玩家測試
本文分析了一款2D休閑類多人在線游戲的設計與實現(xiàn)過程,該案例以Unity3D游戲引擎為開發(fā)平臺,設計及實現(xiàn)了外星人矩陣的移動和射擊算法,使用游戲引擎內置的Unet系統(tǒng)實現(xiàn)了局域網多人聯(lián)網功能,包含服務端和客戶端。經過測試,游戲畫面延遲小、游戲操作同步性高,具有較好的實時性。案例的設計思路和實現(xiàn)過程,對于網絡游戲開發(fā)和教學起到了借鑒作用,可供參考。