技能系统及其同步--MMO服务器开发技术点记录
技能系统及其同步--MMO服务器开发技术点记录
技能系统可以单独开发个组件。下面来介绍一下常见的CombatComponent的设计思路。和移动组件一样,技能组件的同步同样需要进行插值、预测。
我们的技能系统先设计的简单些,只有普攻和特殊技能。
普攻
普攻的执行逻辑是这样的:
- 客户端发起普攻请求,包含目标信息和技能信息,同时本地播放普攻动画;
- 服务端接收到请求后,进行合法性校验,执行普攻逻辑;
- 服务端生成攻击事件,并将事件信息广播给所有相关客户端;
- 客户端接收到攻击事件后,根据事件信息进行本地状态更新和动画播放。
注意这里是直接在服务端执行攻击逻辑更新玩家状态后,将结果同步过去,而不是同步攻击事件在客户端执行。这样首先能保证数据的一致性,然后只同步动画状态可以将战斗逻辑放在服务端,减少客户端的开发负担。
普攻一般是由cd的,也就是我们所说的前后摇,只有在前后摇执行完后的攻击逻辑才会生效。所以攻击组件需要记录cd结束时间 _next_normal_attack_time。cd时间受玩家攻速影响(属性),这不是讨论的重点,先不管。
一般是立即同步动画状态,然后设置定时器在前摇结束后执行攻击逻辑,再同步攻击结果状态(受击动画和新属性状态)。具体的攻击逻辑根据需求来编写,一般使用玩家的位置信息进行某种算法的计算即可,比较简单。
技能
技能多种多样,但是可以统一成一个类的不同子类。技能类的设计如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class ISkill {
public:
virtual ~ISkill() = default;
inline void set_active(bool active) { _is_active = active; }
inline bool is_active() { return _is_active; }
virtual void reset() { set_active(true); }
virtual void destroy() {} // 释放技能占用的资源
virtual void execute() = 0; // 自定义执行技能逻辑
CombatComponent* get_owner() const { return _owner; }
void set_owner(CombatComponent* owner) { _owner = owner; }
private:
bool _is_active = true;
CombatComponent* _owner = nullptr;
};
再根据自己的需求去编写不同的子类即可,是需要开放一些固有接口即可。
技能组件需要管理这些技能,控制这些技能的生命周期,包括创建、销毁、激活和停用等操作。负责触发这些技能,触发逻辑和普攻类似。
预测和回滚
这里目前的实现比较简单,就是判断技能能否释放,不能则回滚蓝值和cd。如果想要了解成熟的战斗系统的回滚方案,可以参考2017年暴雪的gdc分享中的网络同步部分。这个部分我也会找个机会单独写篇博客来讲解学习。
This post is licensed under CC BY 4.0 by the author.