基于Unity3D的多人在线游戏案例设计与实现
2022-01-08章国雁
章国雁
(安徽工商职业学院,安徽 合肥 231131)
目前,国内外许多学者对于利用游戏引擎进行网络游戏开发进行了大量的研究,如刘贤梅等利用Unity引擎为平台,采用 MVC 架构实现了一款ARPG类型多人在线游戏;李伟在Unity3D的基础上与网络通信原理相结合,采用预测式位置同步的方式减少网络延时带来的误差;干建松基于Unity引擎的Unet模块实现了局域网的多人联网游戏功能;吴晶晶等基于Unity3D引擎结合协同程序技术实现预先式同步数据读取,实现了一款MMORPG类型的网络游戏;薛玉倩介绍了基于Unity3D的网络游戏总体设计与实现程序。以上学者研究,对于网络游戏的开发技术起到了积极的推动作用。本文在前人的研究基础上实现了一款多人在线游戏开发案例。
1 案例开发平台
本案例以Unity3D游戏引擎为开发平台,实现一款局域网多人联网游戏,包含服务端和客户端。网络功能使用游戏引擎内置的Unet系统进行开发,该系统提供了NetworkManager网络管理组件进行服务端和客户端的创建,NetworkIdentity网络标识组件进行网络中每个物体的标识,NetworkTransform网络传输组件进行网络同步等。
2 游戏设计与实现
2.1 资源导入和创建预制体
导入案例资源图片到Unity3D引擎,修改图片类型为精灵Sprite,添加刚体组件Rigidbody2D和盒形碰撞器组件BoxCollider2D等,添加完成后创建为预制体。
2.2 游戏联网和网络同步
网络游戏涉及到服务端和客户端的创建、网络地址和端口号、网络中各类物体包括玩家的标识、网络同步等问题。案例采用Unet系统的NetworkManager组件进行游戏网络的管理,网络地址设置为localhost(本机),端口号为7777;在出生信息SpawnInfo一栏,注册客户端玩家、外星人、子弹等网络游戏中需要进行实例化生成的物体。NetworkManagerHUD组件进行游戏服务端和客户端创建的UI界面显示。对网络游戏中的物体添加NetworkIdentity组件进行网络唯一标识和添加NetworkTransform组件进行网络同步。
3 游戏算法及实现
3.1 创建外星人矩阵
游戏初始界面需要生成3行10列的外星人矩阵,同时矩阵保持左右水平移动,每次到达水平边界时,向下移动一个距离。程序设计思路为,通过定义一个动态数组来存储外星人矩阵数据,循环语句生成外星人数据后存入动态数组。以生成第一行的外星人为例,其核心代码如下:
public GameObject alien1Prefab;//第一种外星人预制体
public List
//服务端启动时调用
public override void OnStartServer() {
float startx = -8; //表示在-8这个列的位置
for (int i = 0; i < 10; i++) {//循环语句实现外星人数据生成和存储
CreateAlien(alien1Prefab,startx,12); //在12行的位置生成第一种外星人Alien1
startx += 1.6f; //每次偏移1.6的距离,保证alien图标不重叠
}
}
//创建外星人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); //同步生成到客户端
}
3.2 玩家控制分离和移动同步
在客户端中,当多个玩家进行网络游戏时,用户只能控制当前设备上的玩家,需要对玩家的控制权限进行分离。当玩家移动过后,需要保持其他客户端网络同步状态。程序思路为通过isLocalPlayer属性值判断是否为当前玩家,如果不是则不能进行控制;当前玩家进行移动操作后,发送一个同步命令,其核心代码如下:
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; //如果死亡状态,则返回
moveX = dx;
GetComponent
}
3.3 玩家开火和销毁外星人
游戏实时监控用户的输入指令,当用户按下鼠标左键或者空格键时,玩家开火发射子弹,并在网络中进行同步。其开火函数的部分代码如下:
public GameObject bulletPrefab; //玩家的子弹预制体
[Command]
private void CmdShoot() {//开火函数
//实例化生成单个子弹物体
GameObject myBullet = (GameObject)Instantiate(bulletPrefab,
transform.position + Vector3.up, Quaternion.identity);
NetworkServer.Spawn(myBullet); //在网络中同步生成子弹
}
3.4 外星人攻击的算法及实现
由于游戏生成了3行10列的外星人矩阵,为了游戏的可玩性考虑,游戏设计时做了限制,初始状态只允许最下面一行的外星人可以发射子弹,而上面两行的外星人暂时不能发射子弹,当下面的外星人被销毁时才可以发动攻击。实现算法思路为,遍历外星人动态数组的每个元素,寻找跟当前元素同一列的下一行外星人,如果能找到,则当前元素外星人不能发射子弹,如果寻找不到,则当前外星人为最下面一行,可以发射子弹。
3.5 子弹的设置
给子弹物体增加触发器组件,程序判断其他物体进入子弹触发器范围时,则销毁该物体,同时销毁子弹自身。以玩家子弹为例,如果进入触发器的是外星人,则销毁外星人物体和子弹自身。其触发器核心代码如下:
void OnTriggerEnter2D(Collider2D collider) {//collider指的是碰撞的物体
AlienInvader hitAlien = collider.gameObject.GetComponent
if (hitAlien != null) {//判断是否碰撞到了外星人
NetworkServer.Destroy(hitAlien.gameObject);//消除外星人
NetworkServer.Destroy(this.gameObject);//消除子弹自身
}
}
3.6 计分和游戏UI界面
良好的UI界面有助于提升游戏体验,目前业内普遍采用的UI制作工具主要有uGUI和NGUI,其中uGUI是Unity3D引擎内置的制作工具,制作方便灵活;NGUI是一款专门用于UI制作的插件,功能强大,但需要单独进行安装。本案例采用uGUI系统进行UI界面的制作,使用Canvas画布、Text文本、Image图像、Button按钮等控件搭建了游戏的登录界面和游戏的运行界面,登录界面包含创建主机UI和连接主机UI,运行界面包含计分UI和生命值UI。
4 发布测试
案例制作完成后,可以发布到本地PC端进行功能测试,如图1所示,玩家控制已经分离,多个客户端保持同步状态,具备局域网多人在线游戏的联网功能,具有较好的可玩性。
图1 多人在线玩家测试
5 结束语
本文分析了一款2D休闲类多人在线游戏的设计与实现过程,该案例以Unity3D游戏引擎为开发平台,设计及实现了外星人矩阵的移动和射击算法,使用游戏引擎内置的Unet系统实现了局域网多人联网功能,包含服务端和客户端。经过测试,游戏画面延迟小、游戏操作同步性高,具有较好的实时性。案例的设计思路和实现过程,对于网络游戏开发和教学起到了借鉴作用,可供参考。