【UE】从零开始的UE4游戏制作 入门-蓝图-同步-专属服务器-后端服务器架构-linux部署
前言
研究生期间听过这么一段话,你知道了但不去做和你不知道是两种概念。2个月的时间,让我从什么都不知道成长到知道自己什么都不知道的程度,就算是最大的收获了吧。
一 入门
UE4版本选择
UE系列的各个版本兼容性极差,一上手就用新版本是非常坑的选择,因为既没有多少可以直接copy的项目,也会在按教程学习的时候因编辑器更改了某些属性的位置、名字、函数、语法格式茫然无措,而且还可能遇到各种未知BUG。4.18以下的版本在网上都可以找到很多成品项目、完整教程,算是比较容易上手了。
蓝图/C++
蓝图使用方便易上手,C++可调用接口多但是编译麻烦,两者可以混合使用。但是蓝图非常非常非常不适合复杂逻辑,比如说:
盗来的图哈哈,虽然一般也不会有这么复杂的功能。另外还有一点,如果是多人协作的话少用蓝图为好,UE4中蓝图保存为二进制文件,C++还是普通的CPP文件,如果有一些耦合性高的功能,要不然交给一个人做,要不然用纯C++做。两个人同时修改一个蓝图类,为了解决冲突的时间可能比做两个蓝图还要长…
网络UE4入门视频教程(中字,翻译勉强可看)
链接:https://pan.baidu.com/s/1CeTpnk1dCAPN2TlKEoBZcA
密码:z99x
因为时间不够没有全部看完,只看了1-46。除了部分地方翻译靠脑补,整体还是不错的~
学习UE4在Editor中的基本操作,常用术语,设计理念,如何使用纯蓝图设计完整的demo。
UE4 Dedicated Server
官方教程,如何搭建UE4的专属服务器。
UE4中,一个游戏房间等于一个dedicated server(简称ds),ds判断满足一些条件后开启一个level(包含游戏核心玩法的一局对战),玩家通过ue4 client连接到dedicated server开启游戏。
因为UE4的客户端和服务端逻辑(代码)写在一起,所以在更新代码后,需要vs重新编译两次(editor版,server版;如果是linux版,还要再生成两次)、UE编辑器再compile一次(更新vs的编译信息);在编辑器中的改动则不需要vs编译。
写逻辑时也必须判断哪些东西应该在服务端展现(如重要变量的修改,状态同步等),哪些不能在服务端执行(如UI,表演动画效果等)。如果把伤害判定交给client去做无疑给外挂更多的可乘之机;如果把动画在服务端播放,DS会因为没有动画组件而给出警告。
RPC同步机制:
https://docs.unrealengine.com/en-us/Resources/ContentExamples/Networking
游戏世界对每一个player都是隔离的概念,即使玩家在同一场游戏,玩家看到的所有变化都是服务端的一个拷贝(有玩家A玩家B服务端C,每个玩家控制一个character,则共有6个actor,A/B/C分别有两个actor : character A/character B)。也就是说,玩家在自己的世界中的操作(如行走、跳跃、开火等)并不能被其他玩家和服务器看到(只是修改自己世界中的内容),需要有一个管理员(服务器,或者某一个客户端)处理这种改变世界状态的行为并且判断这种行为是否合法,然后将这种变化更新到其他所有客户端。好在UE4提供了完整的RPC同步机制,非常方便的实现同步(暂先不考虑网络延迟、丢包等其他因素)。
按照个人理解,RPC同步可以分为:1.变量同步2.事件同步3.对象同步。对象是UE世界中一种实体,包括Actor、Character、Pawn等(类似于C++的类对象)。场景中的每一个物体每一块地板都是一个对象,玩家控制的角色也是一个对象。
首先要把对象的属性设为replicated,使对象可以在网络中同步。然后每个对象会有多个事件、函数、变量,选择性的将他们设为同步。
一些重要的逻辑如 玩家A向玩家B开火,玩家B收到伤害 的处理方法为委托服务器执行:
- 对象 : character(玩家控制的角色)、bullet(子弹)
- character有health变量设为replicated
- character A 产生一个 bullet
- bullet设置创造的地点、飞行速度、有效范围、生命周期等,向指定方向发射
- bullet发生碰撞,产生damage【UE4接口ApplyDamage】
- character B接受damage【UE4接口EventAnyDamage】,获取伤害值,执行OnTakeDamage事件(run on server)
- OnTakeDamage执行OnTakeDamage函数,修改character B的health
- RPC会自动将该health同步到其他所有客户端,其他所有客户端的character B角色的health被修改
一些普通的逻辑如人物跳跃考虑先放在客户端执行后同步到服务端。
特别注意:将变量设为RepNotify,蓝图中会自动生成对应的OnRep函数(C++中需要自己添加),OnRep函数在变量改变时自动在每一个客户端上执行(也包括服务端),一般用于特效的播放或者UI的修改如血条变少。记得加上条件的判定不要在ds上执行(因为ds没有这些组件),在debug时当然一切ok,打包成ds后会疯狂报warning:Accessed None trying to read property XXXX.
如何识别client、listen server、dedicated server:https://www.lanindex.com/ue4-shootergame-server%E7%A0%94%E7%A9%B6/
UI制作
https://api.unrealengine.com/INT/Engine/UMG/QuickStart/2/index.html
主要是用户交互界面设计,简单了解,不过多涉及
AI制作
呃……好吧,没做过研究。控制PVE中E的行为模式以及PVP中某些情况(如匹配人数不足)模拟P的行为。也是独立的一套体系,需要设计算法使AI的行为更智能。小Demo就不考虑了。
动画制作
http://api.unrealengine.com/INT/Gameplay/HowTo/CharacterMovement/Blueprints/index.html
即使不是做前端客户端的,这部分内容也需要了解。包括动画是如何同步、如何进行状态转换(令人头皮发麻的行为树)、如何抄袭其他项目的素材
学习优秀的DEMO
https://github.com/tomlooman/EpicSurvivalGameSeries
站在巨人的肩膀上,看得更高。这个项目似乎是官方demo,地图很大,也有一定的操作性和可玩性。项目结合蓝图和C++,对于学习有很大帮助(才不是因为觉得好玩才推荐的O.O)
Socket编程基础
UE4无论是美工美术、背锅侠策划、码农程序都是容易上手的利器,但也并非全能。对于后台开发来说,UE4没有用户登录、连接、商城、大厅、结算等等的相关接口,即UE4针对游戏的核心玩法提供接口,对游戏周边逻辑服务不提供支持。这一部分终于轮到后台来完成啦。
考虑性能等方面,使用linux作为服务器,epoll实现非阻塞socket。有几本入门的书值得一看:《Unix网络编程》、《Linux高性能服务器编程》
参考一些epoll相关的文章:
https://blog.csdn.net/hnlyyk/article/details/50955053
https://blog.csdn.net/qq_25425023/article/details/70199133
https://blog.csdn.net/davidsguo008/article/details/73556811
https://www.cnblogs.com/zhuwbox/p/4222547.html
使用一些第三方模型也是很好的选择:https://aceld.gitbooks.io/libevent/content/
多线程基础
https://blog.csdn.net/qq_25425023/article/details/70199133
https://www.cnblogs.com/wangguchangqing/p/6134635.html
多线程是可选项,取决于实际的项目需求。如果仅仅只有几百人在线(并非游戏中,而是在与后台服务器做数据交互),完全可以使用单线程。多线程设计时考虑在加锁解锁的时间损耗、设计难度和单线程瓶颈之间做权衡。
服务器架构
https://www.lanindex.com/如何管理ue4-server/
团队项目中,合理拆分功能模块至关重要。这篇文章给出了基本的UE服务器架构,还有一些关于服务器设计的思考.
二 开发
开发方式
有幸和通信大佬@sun一起合作,某科(笑)班出身的@我是小白菜一棵.从工具到代码几乎啥都不会.---->我的反应:
Window10有什么好用的,兼容这么渣,用啥VS2017啊?卡爆了!
WTF??Win10居然自带linux系统
VS2017居然可以调试linux代码还能设断点
居然还有VSCODE这种神器编辑器
Xshell是什么…原谅我只用过putty
微软一生吹
-----------------------------------------------------------------------------------
题材:选择第三人称FPS,因为有游戏经验,逻辑清楚,UE4自带TPP模板
模式:快速迭代,先按计划完成预期目标,然后在这个基础上扩展功能
语言:
UE中蓝图(主)/C++(辅)并用,蓝图处理游戏核心逻辑/UI/特效等,C++只负责socket通信;
服务器使用C++/linux
环境配置
Windows 10 i7 8核 16G内存 GTX1060 6GB显卡
Windows Subystem Linux
VS2017(可远程调试linux)
UE4.18.3(包含编辑器版本和源代码版本,并且已经生成了Windows和Linux的编译版本)
Git2.18.0
C++11
系统功能
- 人物系统,包括人物动画(t)
- 枪械系统,包括枪支模型/子弹模型(s)
- 伤害系统,包括人物的伤害判定(t)和子弹的伤害判定(s)
- UI,包括登陆UI(s),匹配UI(s),游戏菜单UI(t)
- 后台服务器,包括登陆服务器(s),大厅服务器(s),DS管理服务器(t)
- 安装和部署,应在windows下生成UE客户端,Linux下部署UE服务端(t)
游戏逻辑并不复杂,因为我们对UE4都是完全新手,在UE相关部分都遇到了些问题,参考http://www.mrtblog.cn/?p=820
系统结构
限制条件:只有两台主机,局域网内UE4无法互通(原因不明,可能是被屏蔽也可能是用法不当)
经过分析讨论到最后实现,设计出的服务器架构如下
CL:UE4客户端(玩家的登陆客户端)
LGS : LoginServer(登录服务器)
LBS : LobbyServer(大厅服务器)
CS : ControlServer(DS管理服务器)
DS : Dedicated Server(UE4服务端,专属服务器)
INFO : 传递的socket数据,内容为IP和端口号
data : 传递的socket数据,任意内容
完整的游戏匹配行为如下:
- 用户登录,CL向LGS发送登陆申请(data)
- 用户进入大厅,LGS动态获取LBS的INFO,返还给CL
- 用户发起匹配,CL按照INFO向LBS发送连接申请,之后发送匹配申请
- 系统匹配,LBS从匹配池中取出3名玩家,并向CS申请UE4 服务器地址(DS)
- 获取空闲房间,CS搜索DS列表,获取INFO,向指定DS发送data
- 房间开启,DS开启关卡,返回data给CS
- 转发,CS接收到data,将INFO发回给LBS
- 转发,LBS将INFO转发给CL
- 开启游戏对局,CL直连DS
未完成的部分
因为时间有限,部分预想的功能未完全实现,但是实现上并不困难
- DS的自动开启和关闭 : 可以在sh脚本编写内容,由CS调用不同的sh脚本实现
- 积分系统 : 添加gamemode/gamestate/playerstate 记录用户的击杀和死亡数,游戏结束时上传到LBS,LBS将数据保存到MYSQL对应表中
- 聊天 : 新增聊天服务器ChatServer,为CL和ChatServer建立TCP,在CL内添加聊天框,实时打印接收到的聊天数据
LGS和LBS
这部分完全由@sun完成,加入了自己的协程库,以及使用VistualGDB调试代码,而且还使用了Socket的一些新特性.出现setsockopt(): Protocol not available的错误则需要注释掉setsockopt的这部分代码(似乎是可以使TCP多个进程绑定在一个端口上).协程库没有研究过,摊.
其他
游戏逻辑和服务器通信是基础中的基础,在海量用户涌入时的负载均衡,服务器宕机的容灾应急措施,匹配机制如何合理的塑造公平竞争环境,这些才是更值得关注的问题,只有实际去运营一款游戏才能慢慢摸索到其中的解决方案.
代码
简陋的代码,如果继续从事游戏行业的话,希望若干年后自己会回来重构一遍(每个游戏从业者都有着一个自研独立游戏的梦吗)
https://github.com/vcingit/UE4_TPP_WITH_CPP_DEVEPLOPMENT
结束语
离别的时候总是伤感的,感谢两个月认识了诸多有爱的小伙伴:低调沉稳@sun,通情达理@liu,八面玲珑@chen,洞无城府@pan,放达不羁@wang,还有含而不露@li.大家都是心怀理想又懂得生活的人,无论身在何处,希望都能殊途同归,到达理想的彼岸.
[完]
赞一个
请问github的代码能重新上传一下么,谢谢!
因为算是保密的东西,所以代码就不放啦
你好 我最近也在做一个完整的ue项目 有些困惑 可以加个好友咨询一下吗
欢迎交流
请问下 UE 上能集成 libevent 吗?