Post

技能系统及其同步--MMO服务器开发技术点记录

技能系统及其同步--MMO服务器开发技术点记录

技能系统可以单独开发个组件。下面来介绍一下常见的CombatComponent的设计思路。和移动组件一样,技能组件的同步同样需要进行插值、预测。

我们的技能系统先设计的简单些,只有普攻和特殊技能。

普攻

普攻的执行逻辑是这样的:

  1. 客户端发起普攻请求,包含目标信息和技能信息,同时本地播放普攻动画;
  2. 服务端接收到请求后,进行合法性校验,执行普攻逻辑;
  3. 服务端生成攻击事件,并将事件信息广播给所有相关客户端;
  4. 客户端接收到攻击事件后,根据事件信息进行本地状态更新和动画播放。

注意这里是直接在服务端执行攻击逻辑更新玩家状态后,将结果同步过去,而不是同步攻击事件在客户端执行。这样首先能保证数据的一致性,然后只同步动画状态可以将战斗逻辑放在服务端,减少客户端的开发负担。

普攻一般是由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.