一、游戏物品/道具系统数据模型设计特点
为了让游戏更加的丰富,我们1201团队的新手机游戏设计了道具系统。于是丰富了游戏、取悦了玩家,哭了开发——道具/物品数据子系统是简单的、复杂的、不确定的:
- 简单,说起来不就是选择一个或多个数据库产品,然后定义一种数据模型,然后增、删、改、查。
复杂,物品/道具可以在细分为装备、时装、坐骑、宝石、buff等等,每类物品有不同的属性需求,于是:
- 首先物品数据是游戏核心数据里数据量最大、操作最频繁、数据结构最多元化的数据
- 如果用一种数据表结构,那么会浪费很多的字段或数据空间(而物品表超大);
- 如果用不同的数据表结构,那么游戏逻辑就要麻烦一些了,比如物品在玩家中转移的时候、修改、丢弃的时候。
- 是否进行应用逻辑层水平切分?切分了就可以将数据库分布到多个数据库服务器上,那么理论上数据规模就不会成为瓶颈了;但如果切分了,道具数据分析、后期的合区逻辑就会很复杂。
- 装备、时装是会有多个属性的,且每件装备的属性值、属性类型都不一样,如何设计数据字段(当然如果用nosql数据库就不存在这个问题了)?
不确定:
- 随着游戏开发及运营的进行,各种新的道具的需求会不断涌现出来,有可能就会需要增加新的属性和功能需求
- 到底每一个玩家最终会有多少的物品?
- 最终单个区服的数据规模有多大这个其实很难预计。我们做的很完善(当然开发代价也大)的设计与开发会不会有些多余,甚至被老板认为想多了?
二、游戏物品/道具系统数据模型设计目标及解决思路
上面分析做了,槽也吐了,还是要做事嘛,呵呵。根据我们的新游戏的具体需求,对物品数据库表的设计定义了如下要求和解决思路:
1 | 确保数据操作的性能 | 充分利用缓存服务器 |
2 | 降低程序开发和后期客服工作的复杂度 | 各类道具不分表 |
3 | 必须可以方便、灵活的支持道具新功能需求的开发 | 将多变的装备属性以json格式存于一个字段 |
4 | 保留充分的可扩展性 | 根据玩家id进行数据库表水平切分 |
5 | 尽量降低合区操作时数据处理逻辑的难度和效率 | 用自增长ID、玩家id、区服id做联合主键 |
三、具体开发设计方案
根据以上的分析结果,我们在总结了以前的游戏开发经验并参考了网上的一些文章后形成了我们新手机游戏的物品数据子系统的设计、开发方案。
所有数据访问都封装在model层。
- 在程序的model层里定义公共函数GetDb(playerid,areaid),用于物品数据及其它需要进行按用户水平分割的数据获取数据库(连接)
- 每一个物品的主键由itemid,playerid,areaid三个字段组成
- 将装备buff及某道具特有属性统一以json字符串形式保存在一个varchar字段里
- 道具表定义 失效时间 字段,这个字段同时表示道具有效期的三种情况:
- =0 ,表示是不限时的永久性道具
- 小于等于600000,表示有效时间段,如双倍经验卡有效时长3小时,那么着个字段值为 180 (分钟),使用此道具时,用当前时间加上这个字段值得到失效时间戳修改此字段或做其他处理
- 大于600000,表示该道具的失效时间戳(unix时间戳格式)
- 玩家道具数据查询流程:
- 首先检查redis里有没有
- 如果有,返回
- 如果没有从数据库里查询并存到redis,返回
- 修改/或增加道具数据流程:
- 首先检查redis里有没有
- 如果没有,从数据库里查询并存到redis
- 如果有,继续
- 修改/增加redis数据,同时在key为“item_update_list”的redis list 数据里记录下该道具的主键
- 定时根据“item_update_List”数据写回mysql,并清除“item_update_list”
- 删除一个道具数据流程:
- 在redis 里key为“item_delete_list” 的redis list 数据里记录下该道具的主键
- 删除redis里记录
- 定时根据item_delete_list”数据删除mysql里记录,并清除“item_delete_list”
8.注意: - 配置redis 为 在每次更新操作后进行日志记录
- 缓存定时同步mysql处理程序可以作为一个独立的进程运行
- 这个解决方案可以针对其它用户私有数据,如技能、buff。
四、总结
数据库表水平分割和缓存应用基本上已经是服务器端程序员的常识,在google上查相关技术资料时,大多数博文也是写的这些。
本文先是对游戏道具/物品数据模型的进行了简单的需求分析,然后讲了思路和方案,其实我最想表达的是我的三个设计细节或idea:
+ 道具数据记录主键设计(方便合区)
+ 装备buff及道具特有的属性字段设计(为道具丰富的功能需求提供灵活、便捷的数据基础)
+ 所有道具类别不区分存储(方便后期的客服查询和数据统计)
最后声明:
其实我是一个程序员,呵呵!