给一个已经定型的游戏添加哪怕是一个小特性,都是棘手的事情,很容易引入新的bug,或者破坏已有的功能。复杂的联网更是如此,它涉及到的改动几乎遍及系统的方方面面。玩家的一举一动都需要在其他人的屏幕上展现出来,所以我们需要选择一个低成本的,容易实现的方式,来开发多人在线的功能。

技术选型

Unity引擎内置了多人联机的解决方案,涵盖了从最底层的网络数据传输,到不同玩家之间的消息发送,再到游戏大厅这样的高级功能。考虑到Unity官方提供的云服务(Internet Services)在国内的延迟较高,而且需要付费,我们决定采用Steam与Unity相结合的方式。底层用Steam发送网络数据包,中间由Unity负责把各个包整合成游戏逻辑所需要的格式,高层的大厅也使用Steam提供的服务。

说到这里要赞美一下Unity Networking的模块设计,它把具体的网络数据传输细节和抽象的消息发送功能分离开来。使得开发者既可以使用传统的“IP地址+端口”的方式实现玩家之间的连接,也可以相对方便地接入Steam或WeGame,利用这些平台SDK包含的更高级的功能去收发网络数据。而且Unity的网络模块是开源的,不仅方便查阅,还可以根据自身需求进行修改,然后替换掉引擎自带的模块。

服务器

联网游戏需要一个服务器,用于协调多个玩家之间的游戏进程。否则大家的电脑有快有慢,很容易出现游戏节奏不一致的情况。比如,玩家A的电脑配置高,运行流畅;玩家B的电脑有点卡,会掉帧。那么,当游戏需要3个小飞碟从上方飞入屏幕攻击玩家的时候,可能玩家A那边的飞碟已经全部就位,开始发射子弹了;但玩家B那边刚刚创建出第二个飞碟。这样就导致不同玩家屏幕上显示的内容完全不同,很难进行正常的游戏。引入服务器就是要避免出现各种各样的不一致行为,让速度快的机器等等速度慢的,大家尽可能保持相同的步调去执行游戏逻辑。

这个服务器可以是独立的后台,就像一个网站那样托管在某个云计算厂商那里;也可以让某个玩家来充当服务器,在运行自己游戏逻辑的同时也负责调度其他玩家的游戏。不过,开发并维护一个独立服务器的成本相对而言还是挺高的,所以我们选择了第二种方案,就让创建房间的玩家来兼职做服务器。Unity恰好有一个Host模式,支持一个玩家同时扮演服务器和客户端。

游戏房间

完成了前期的技术准备后,我们就开始着手制作游戏房间。目前我们仅支持双人协作,这部分的流程也比较直观:

玩家在新建的房间内独自选择角色,并等待

其他玩家加入房间后选择自己的角色
  • 创建房间:玩家A向Steam发起申请,并设置最大人数为2。如果成功,A就成为房间的所有者,进入角色选择界面。同时,A还需要启动服务器(NetworkServer),等待其他玩家的进入。
  • 查询房间:玩家B设置筛选条件去查询当前列表,Steam会返回还有空余位置的房间。如果A创建的房间符合条件,该房间就会包含在返回结果之中。
  • 进入房间:B申请进入A创建的房间。如果成功,A和B之间就可以通过Steam互相发送消息。但这时房间内的玩家只能进行基本的通信,还不能利用Unity提供的状态同步等机制。
  • 建立C/S关系:B向A发送连接请求(NetworkClient),A收到后建立连接。这样,后续的游戏同步逻辑就可以按照Unity的方式进行。
  • 开始游戏:B进入房间,选择自己的角色。二手手机号码交易完毕后,A通知双方加载游戏场景。

角色同步

双人同屏战斗

游戏角色作为玩家的控制对象,接收绝大部分用户输入,是同步的重点。

  • 移动:Unity提供了同步物体位置、旋转的组件(NetworkTransform),可以设置频率调整每秒同步的次数。但每次同步之间没有插值,导致物体的移动显得特别僵硬。所以我们选择自行发送位置数据,远程角色在收到数据后进行平滑处理。也就是说不是立即将角色设置到新的位置,而是以一定速率,每帧逐渐靠近新的位置。这种方式虽然会导致角色的位置跟实际位置有所偏差,但会有一个能够接受的视觉效果。
  • 状态:角色的血量、炸弹数量还有当前动画等通过Unity提供的状态同步方式来处理。引擎自行监控这些特别标注的变量(SyncVar),在初始和变化的时候,把新数值同步到客户端上去。
  • 技能:释放技能和炸弹由玩家自己控制的角色发起,在服务器端执行,然后同步到其他玩家的客户端。这种类型的操作适合使用Command+ClientRpc方式去实现。
  • 子弹:自机的子弹也是通过监测当前是否正处于发射的状态去同步。角色或敌机中弹则作为事件发送到服务器去处理。

场景同步

游戏场景占据了最多的工作量,主要是因为之前很多工作都是利用PlayMaker插件来做的。这个可视化的状态机工具能方便非技术人员去调整物体在游戏内的动态行为。截止到目前的1.8.9版本,它还不支持Unity的多人模块,同步起来比较麻烦。

复杂的状态机,其中蓝色高亮显示的是需要强制同步的状态

以下是场景中需要注意的事项:

  • 时间:许多场景的移动、关键动作的触发都跟时间相关,所以当前游戏进行的时间是场景保持同步的关键。
  • 杂兵行为:我们游戏中有一百多个杂兵,基于这些杂兵有八百多个不同的行为。这些行为都是用PlayMaker编辑的状态机。要让如此众多的状态机去支持联网,手动去挨个修改是不可能的,只能利用脚本批量修改。
  • 状态机:我们设计关卡时,会根据游戏进行的时间或者地图移动的位置去指定某个杂兵的行为。这些行为一般遵循先创建杂兵单位,再移动射击,最后被击落或离开屏幕的规律。这里边包含两部分,一是用于交互和同步的杂兵,二是控制杂兵行为的状态机。在单机情况下,状态机创建出单位紧接着执行后续操作;在联网模式下为了状态同步,场景中物体的创建和销毁需要在服务器端进行。所以,原有的状态机在服务器和客户端上的执行不再一致。服务器创建的杂兵单位,会通过Unity的机制自动在客户端上克隆出来,这样客户端不再需要自己创建,而是等待单位被服务器创建出来后作为参数传入状态机里去执行后续动作。
  • Boss行为:一般的杂兵行为比较简单,在屏幕中存在的时间也较短,在服务器和客户端上各自运行也不会产生太大差别。但Boss的行为比较复杂,运行一段时间后就会出现明显偏差。我们在状态机内部的关键节点上加入等待机制,让各玩家在运行到节点处同步进入下一状态。

总结

至此游戏已经可以支持基本的多人体验了。对于联网功能的开发,我们总结了以下心得:

  • 给基于Unity引擎的游戏添加联网功能的难度并不大,但最好在游戏设计初期就确定是否单机还是在线游戏,能少走弯路,节省工作量。
  • 定期清理工程文件,做好素材分类,尽可能多地复用资源,避免冗余。这样能减少项目后期的维护成本。
  • 在写这篇文章时,碰巧看到关于帧同步的介绍。感觉这项技术对于弹幕这种精确度要求较高的游戏可能更加合适。将来有机会在新的项目中尝试。

基于Unity的弹幕游戏多人联机尝试相关推荐

  1. 【基于unity制作的游戏】《ZERO:天元》

    简介 <计算与人工智能概论>期末大作业项目 项目名<ZERO:天元> 类型:游戏 米呼游詹姆斯·克拉克·麦克斯韦方程组工作室出品 故事背景: 弗兰大学研究生唐可可一日从寝室醒来 ...

  2. 上班最强摸鱼游戏-多人联机小游戏 (一)

    highlight: a11y-dark 多人在线射击游戏.最强摸鱼游戏 在想体验地址====> github地址: 开发不易,多谢大哥大姐们点个start吧,点个小爱心吧 技术栈 canvas ...

  3. Unity Netcode for GameObjects多人联机(源文件)

    一.安装Netcode for Gameobjects Netcode for Gameobjects是Unity新推出的联机解决方案,该解决方案目前处于初期,相关功能不是很完善,但是用起来还不错.下 ...

  4. 《基于Unity的2D多人乱斗闯关游戏设计与开发》--小组博客综述

    文章目录 项目名称 项目背景 项目简介 项目架构 项目特色 大致功能需求 游戏模式/内容 项目技术选型 项目分工 项目具体计划 此次项目实训不完全按照项目计划书进行,因为游戏范围太广,可能随时调整游戏 ...

  5. 多人联机的俄罗斯方块游戏(C++),游戏规则模仿任天堂Tetris99,基于qt,kcp,protobuf,qslog。

    目录 Tetris 游戏截图 游戏菜单 1v1对战 9人对局 游戏特性细节介绍 攻击机制 Tetris标准特性 Super Rotation System(超级旋转系统) 7 bag system ( ...

  6. Unity Networking开发多人联机射击游戏

    UNet开发多人联机射击游戏 引言: Networking作为Unity官方的用于开发多人在线游戏的网络模块,开发者可以不用自己搭建网络模块的底层,通过使用Unity提供的一些相关组件,可以轻松实现简 ...

  7. 基于Unity的多人协作游戏开发

    基于Unity的多人协作游戏开发–第一次迭代 小组成立与大型应用软件设计第一周课堂,小组由一共5名成员组成,由王虎林担任组长,组员分别是:陈志健 李子钊 杨捷 林博韬.下面将是我们第一次迭代的主要历程 ...

  8. 从零学习游戏服务器开发(一) 从一款多人联机实时对战游戏开始

    写在前面的话 经常有学生或者初学者问我如何去阅读和学习一个开源软件的代码,也有不少朋友在工作岗位时面对前同事留下的项目,由于文档不完善.代码注释少.工程数量大,而无从下手.本文将来通过一个多人联机实时 ...

  9. 游戏设计、原型与开发:基于Unity与C#从构思到实现pdf

    下载地址:网盘下载 这是一本将游戏设计理论.原型开发方法以及编程技术巧妙结合在一起的书籍,目的是填补游戏设计与编程开发之间的缺口,将两者联系起来.随着 Unity游戏开发技术趋于成熟,游戏设计师把自己 ...

最新文章

  1. net user命令详解
  2. 【从0到1学Web前端】javascript中的ajax对象(一)
  3. SAP UI5 应用开发教程之五十六 - SAP UI5 树控件(tree)的开发
  4. owasp maven_OWASP依赖性检查Maven插件–必须具备
  5. ajax发送数据时的contentType
  6. 查询链接服务器信息,如何通过 SQL Server 链接服务器和分布式查询使用 Excel
  7. 【NOIP2010】【Luogu1190】接水问题(给定顺序的模拟)
  8. 解决C#中ListView闪烁的办法
  9. 使用wget抓取网站资源
  10. 程序设计语言编译原理-陈火旺(第三版)简答题复习
  11. 普林斯顿微积分读本篇十五:积分方法
  12. linux crontab测试,crontab使用测试
  13. 桌面右下角出现“测试模式 Windows7 内部版本7601”怎么回事?
  14. 无锡工艺技术计算机信息管理论文,无锡工艺职业技术学院05/06学年第一学期.doc...
  15. 别学英语了!微软给PPT和Skype新加的这个功能,让你和老外从此交流无障碍
  16. RabbitMQ-基础(二)
  17. 落枕、肩颈酸痛,用磁疗就可缓解!
  18. python输入一个数字n、计算1到n的和_python用户输入一个整数N,计算并输出1到N相加的和,请问这个程序错在哪里了?...
  19. 【操作系统】操作系统的功能管理与分类
  20. android 手机信号软件增强方案

热门文章

  1. python中while语句的用法_python 使用while循环输出*组成的菱形实例
  2. GAN生成对抗网络-INFOGAN原理与基本实现-可解释的生成对抗网络-06
  3. oracle10g rman备份有效性,验证RMAN备份的有效性
  4. 深度学习总结:用pytorch做dropout和Batch Normalization时需要注意的地方,用tensorflow做dropout和BN时需要注意的地方,
  5. 算法优化:动态规划加速,货物运输问题,四边形不等式, 从O(n^2)到O(n^3)
  6. 正则提取字符串-python
  7. 使用Microsoft Unity进行日志记录
  8. HTML——meta
  9. Python之路_Day13
  10. ubuntu 下使用mysql