基于ET6.0的对战游戏demo
前言
先开个坑,关系到毕业设计的实现。
游戏类型:
战旗类型、分为单机和联网,单机下怪物由AI树驱动,联网进行玩家对战
暂定的网络同步思路
- 状态同步方式
- 位置方面:客户端Unit每隔一段时间将自身的位置、朝向、速度发送给服务器,服务器计算出最终结果后进行广播操作,所有Units对位置结果进行插值处理
12/19更新:现已通过A*方式进行寻路,所以客户端上传位置指令后服务器进行一定的校验、记录后即可进行转发操作,由客户端通过A*寻路移动到指定格子。 - 状态方面(技能、动画等):利用一个状态包来进行转发广播操作,与位置包分开处理
12/19更新:因为制作的是战旗类型游戏,所以调整同步方式为同步玩家的输入指令,由服务器计算伤害数值、角色属性等变化进行广播操作(现在已将伤害的显示逻辑与表现逻辑分离)提供给客户端进行表现。
- 位置方面:客户端Unit每隔一段时间将自身的位置、朝向、速度发送给服务器,服务器计算出最终结果后进行广播操作,所有Units对位置结果进行插值处理
目前进度:
- 弃用ET的自带UI,加入了EGUI的基于ET的UI框架并针对其进行修改和适配,加入UI栈、UI队列等
- 采用ET框架实现A*寻路算法,将具体寻路功能拆分为在zoneScene中全局的A*地图GridComponent组件与移动控制组件ControlComponent
- 初步加入技能系统,可以获取移动/技能范围并对对应格子移动/释放,技能、角色等属性采用导表的方式,方便后期修改
- 战斗场景搭建,并针对画面进行了Bloom、环境光遮蔽等后处理
- 战斗玩家Unit、怪物Unit设计完成,通过彼此的BattleComponent进行交互,符合ECS思路
12/19更新:
RoundMgrComponent实现回合管理,回合顺序初步通过角色自身的速度属性进行排序,后期配合Buff技能会在回合中打乱战斗角色的回合顺序。
加入Buff状态机以及每个角色的BuffComponent即Buff状态组件,可对角色进行Buff的添加、移除(如加攻、防等机制),可实现每回合开始前的Buff判定Tick()(如中毒、流血等机制)
实现四叉树场景管理,对于不在摄像机内的场景Object进行剔除,优化内存
具体文章:基于ET的四叉树场景管理组件
实现技能派生机制(技能组),在策划表填写时可以填写某技能的子技能,在实际调用时会顺序使用其派生技能,因此在使用组合技能时无需通过Animator对每个技能动画进行再组合
技能表的部分参数:实现可视化模块管理,包括伤害数值/特效模块、相机控制模块、四叉树场景管理模块、声音模块等。
其中SoundModule音频管理参考自GameFramework中的思路。
具体文章:
基于ET的模块化管理及其声音模块优化UI流程,添加场景切换加载Loading界面,增加UI淡入淡出效果,新增血条展示,人物状态栏、技能栏等
实现shader的剔除效果模拟slider,新增子UI预置ESNormalSlider(基于Unity的Slider),ESSlider(基于Shader剔除),实现shader的消融效果等。
具体文章:
Shader:透明度混合,平面下的外/内轮廓,立体下的外轮廓,菲涅尔现象,内发光现象总和
Shader剔除模拟Slider效果实现场景地图障碍物(具体障碍物prefab会在预置Obstacle Prefab中随机选择)、怪物、角色自定义生成,方便随时进行地图信息调整。后期拟定会在角色战斗前由玩家自定义调整角色位置。
地图表格:实现怪物AI行为树,提供Sequence、Selector、ETTaskAction等多节点任意组合,提供RandomSequence实现怪物逻辑的随机性:
怪物一般逻辑:如果范围内有敌人则攻击,若没有则向其仇恨玩家移动(1,最大移动距离),若无仇恨玩家则向第一个地方角色随机移动。仇恨机制表示上一次攻击其的玩家。
代码逻辑:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35m_Ai.OpenBranch(
BT.If(() =>
{
if (bc.lastAttackedUnit!=null)
{
CharacterPropertyComponent lastcpc = bc.lastAttackedUnit.GetComponent<CharacterPropertyComponent>();
if (lastcpc!=null)
{
return !lastcpc.isDead;
}
}
return false;
}).OpenBranch(
BT.RunETTask(() => this.OnAttackToUnit(baseUnit, bc.lastAttackedUnit))
),
BT.If(() => { return enemyCells.Count > 0;}).OpenBranch(
BT.RunETTask(() => this.OnAttackToPoint(baseUnit,enemyCells.First()))
),
BT.If(() => { return enemyCells.Count == 0;}).OpenBranch(
BT.RunETTask(() =>
{
//获取随机脚步
Random.InitState(DateTime.Now.Millisecond);
int footStep = Random.Range(1, cpc.moveRange);
//找到距离某个角色的最短路径
//TODO:后续应该优化,当前找到的默认是第一个生成的角色
BaseUnitComponent buc = aiInput.DomainScene().GetComponent<BaseUnitComponent>();
BaseUnit unit=buc.GetFirstPlayerUnit();
CharacterPropertyComponent unit_cpc = unit.ConcreteUnit.GetComponent<CharacterPropertyComponent>();
return this.OnChasePoint(baseUnit,unit_cpc.PointPos,footStep);
})
)
);实现技能释放的表现和逻辑分离,在释放技能前进行伤害数值计算,后期在Server中单独执行伤害技能的伤害数值计算、Buff逻辑计算、并调整角色属性,客户端仅做表现。
- 每个技能分为Action和Effect,Action控制使用者动画播放,Effect控制技能特效、战斗数值等表现。
游戏主界面设计,目前已完成初步主界面UI,后续拟定通过Camera在游戏实际场景中的巡逻作为背景