战斗系统架构设计
ARPG游戏的战斗模式
一般ARPG游戏的战斗模式
请求服务器开始战斗,校验合法则开始加载战场资源
玩家操控角色施放技能
本质就是控制角色播放动作
对应时间点播放技能特效与音效
计算攻击范围与伤害
保留相应运算结果,战斗数据发往服务器校验
结果合法则发放关卡奖励
战斗逻辑框架
Controller用于表现层(继承MonoBehaviour),EntityBase用于逻辑层
进入战斗副本的流程首先从服务器发出的战斗回应信息通过FubenSys处理
12345678910public void RspFBFight(GameMsg msg){ RspFBFight data = msg.rspFBFight; GameRoot.Instance.SetPlayerDataByFBFight(data);//扣除玩家体力 MainCitySys.Instance.mainCityWnd.SetWndState(false);//关掉主城UI SetFubenWndState(false);//关掉副本选择UI BattleSys.Inst ...
副本系统摘要
副本系统是一个独立出来的业务逻辑,我们需要新建一个FubenSys
大体上FubenSys和MainCitySys的设计是差不多的,需要管理自己的UI Window,需要实现一些副本业务核心逻辑。
在设计上,MainCityWnd只能调用MainCitySys提供的API,如果想用MainCityWnd打开副本选择界面,只能先使用MainCitySys调用FubenSys再打开副本选择界面,这也是设计规范的体现。
副本的PlayerData副本的PalyerData只用一个int定义即可
1public int fuben;//记录当前打到哪一关
然后根据这个PalyerData修改DBMgr即可
初始化的值
1fuben = 10001
副本的界面
我们通过对副本号取余来刷新副本界面
1234567891011121314151617181920public void RefreshUI(){ int fbid = pd.fuben; for (int i = 0; i < btnFubens.Length; i++) { ...
并包流量优化
当我们完成了任务奖励系统后,奖励系统发出的包和其他触发此系统发出的包会同时发送给客户端,这是一种浪费流量的行为,我们可以把两个消息合并来优化流量。
当我们铸造金币,PshTaskPrgs和RspBuy会同时推送给客户端
服务器TaskSys增加GetTaskPrgs12345678910111213141516171819public PshTaskPrgs GetTaskPrgs(PlayerData pd, int tid){ TaskRewardData trd = CalcTaskRewardData(pd, tid); TaskRewardCfg trc = _cfgSvc.GetTaskRewardCfg(tid); if (trd.prgs < trc.count) { trd.prgs += 1; //更新任务进度 CalcTaskArr(pd, trd); return new PshTaskPrgs { tas ...
任务奖励进度检测
任务系统和其他系统打交道很多,比如副本系统、导航系统等,其他的系统用于刷新任务系统的进度。
添加更新任务进度API给TaskSys添加更新任务进度的API
1234567891011121314151617181920212223242526public void CalcTaskPrgs(PlayerData pd, int tid){ TaskRewardData trd = CalcTaskRewardData(pd, tid); TaskRewardCfg trc = _cfgSvc.GetTaskRewardCfg(tid); if (trd.prgs < trc.count) { trd.prgs += 1; //更新任务进度 CalcTaskArr(pd, trd); ServerSession session = _cacheSvc.GetOnlineServerSession(pd.id); if (session != null) & ...
任务奖励配置摘要
任务奖励界面
在这个界面中,任务的名称和任务的奖励信息都是通过配置直接读取就可以,而任务的ID以及进度信息和是否领取就需要配置服务器通信了
任务奖励配置
客户端和服务端的配置类都是继承BaseData
客户端配置类12345678910111213public class TaskRewardCfg : BaseData<TaskRewardCfg>{ public string taskName; public int count; public int exp; public int coin;}public class TaskRewardData:BaseData<TaskRewardData>{ public int prgs; public bool taked;}
这里的TaskRewardData类并不是配置类,而是用来让客户端读取服务端发送过来的任务进度的类
服务端配置类12345678910111213public class TaskRewardCfg : B ...
TimerSvc和PowerSys
引入PETimer之后,就可以整合进服务器和客户端,为它们添加计时服务:
PlaneZhong/PETimer: A C# Timer Tool. (github.com)
服务器TimerSvc12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455using System;using System.Collections.Generic;public class TimerSvc:SingletonPattern<TimerSvc>{ class TaskPack { public int tid; public Action<int> callback; public TaskPack(int tid, Action<int> callback) { this.tid = ...
PETimer(一)
Awake和其他生命周期的区别Awake调用的时机脚本Awake的内容只要挂载它的物体在场景中就能启用。
脚本Start、Update、LateUpdate等的内容需要当前脚本的enable打开才能启用(这种脚本挂载时前面有一个“√”)
OnEnable、OnDisable调用时机当一个脚本第一次调用时,先执行OnEnable再执行Start。之后脚本再次enable或disable只会执行OnEnable和OnDisable,不会调用Start了
FixedUpdate的TimestepFixedUpdate为固定帧率,在Project Settings——Time里面可以设定Timestep,默认0.02即为50帧
LateUpdate一般用作摄像机跟随运算
FixedUpdate的调用FixedUpdate并不是一直保证每0.02秒运行一次,我们可以用下面的代码来测试:
123456789101112131415161718using UnityEngine;namespace DarknessWarGodLearning.Test{ public class F ...
聊天系统服务器通信
服务器Chat通信协定修改服务器的GameMsg,添加聊天需要的类:
12345678910111213#region 聊天相关[System.Serializable]public class SndChat{ public string chat;//服务器通过session可以知道是哪个客户端的消息}[System.Serializable]public class PshChat//世界聊天需要全服广播,使用push来命名{ public string name; public string chat;}#endregion
服务器ChatSys首先给CacheSvc添加获取所有在线客户端的方法:
123456789101112131415161718192021222324252627282930313233343536using PEProtocol;using System.Collections.Generic;public class ChatSys:SingletonPattern<ChatSys&g ...
强化系统配置摘要
强化系统界面
“生命 +216”后面的“216”是数据的累加
强化系统数据表
pos0表示头部、pos1表示身体依次类推
数据XML解析方式强化系统数据表的ID是没有参考意义的,所以使用嵌套字典,第一个字典使用pos当key,第二个字典使用starlv当key
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667#region 强化升级配置/// <summary>/// 第一个int是pos,内部字典的int是starlv/// </summary>private Dictionary<int,Dictionary<int, StrongCfg>> strongCfgDic = new Dictionary<int,Dictionary<int, StrongCfg>>();private void InitS ...
对话窗口和服务器网络配置服务
我们按照配置表当中的文件,使用String.Split为主要方法来把对话内容拆分出来,使用String.Replalce方法来替换角色名字
GuideWnd脚本
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081public class GuideWnd : WindowRoot{ public TextMeshProUGUI txtName; public TextMeshProUGUI txtTalk; public Image imgIcon; public Button btnNextLine; private PlayerData pd; private AutoGuideCfg curtTaskData; public string[] dialogArr; pri ...