如何为含可变属性的游戏数据库实体建模?(含Recipe设计)
游戏内配方追踪数据库的可变输入/输出建模方案
针对你遇到的Recipe可变输入输出的建模问题,不用创建多个重复实体,用关联表+统一资源实体的方案就能完美解决,具体设计如下:
1. 统一Item和Fluid为通用资源表
把Item和Fluid合并到同一个Resource表,存储两者的共同属性,通过类型字段区分即可,避免重复建表:
| 字段名 | 类型 | 说明 |
|---|---|---|
| resource_id | INT(主键,自增) | 资源唯一ID |
| name | VARCHAR(255) | 资源名称(如"铁板"、"原油") |
| type | ENUM('item', 'fluid') | 区分是物品还是流体 |
| description | TEXT(可选) | 资源描述 |
2. 核心Recipe表
存储配方的基础信息,比如生产耗时、能量消耗等,后续通过约束保证至少有一个输出:
| 字段名 | 类型 | 说明 |
|---|---|---|
| recipe_id | INT(主键,自增) | 配方唯一ID |
| name | VARCHAR(255) | 配方名称(如"铁板冶炼") |
| craft_time | FLOAT | 生产一组成品的耗时 |
| energy_cost | FLOAT(可选) | 生产一组消耗的能量值 |
3. 用关联表实现可变输入/输出
创建两个中间表,分别记录配方的输入和输出关系,这样一个配方可以对应任意数量的输入输出:
配方输入关联表 Recipe_Input
| 字段名 | 类型 | 说明 |
|---|---|---|
| recipe_input_id | INT(主键,自增) | 输入记录唯一ID |
| recipe_id | INT(外键,关联Recipe) | 所属配方ID |
| resource_id | INT(外键,关联Resource) | 输入的资源ID |
| quantity | FLOAT | 生产一组所需的资源数量 |
配方输出关联表 Recipe_Output
| 字段名 | 类型 | 说明 |
|---|---|---|
| recipe_output_id | INT(主键,自增) | 输出记录唯一ID |
| recipe_id | INT(外键,关联Recipe) | 所属配方ID |
| resource_id | INT(外键,关联Resource) | 输出的资源ID |
| quantity | FLOAT | 生产一组产出的资源数量 |
4. 其他实体的关联调整
- Node表:添加
resource_id外键关联Resource表,因为Node只输出单个资源,直接关联即可满足需求。 - Building与Recipe的关联:创建
Building_Recipe中间表处理多对多关系,支持一个建筑处理多个配方:
| 字段名 | 类型 | 说明 |
|---|---|---|
| building_recipe_id | INT(主键,自增) | 关联记录唯一ID |
| building_id | INT(外键,关联Building) | 所属建筑ID |
| recipe_id | INT(外键,关联Recipe) | 可处理的配方ID |
关键约束实现
- 保证Recipe至少有一个输出:可以在数据库层面创建触发器,当插入/更新Recipe时,检查
Recipe_Output中是否存在对应记录;或者在业务代码中做校验,创建Recipe前必须先添加至少一个输出项。 - 资源类型校验:如果需要限制某些配方只能用物品/流体,可以在关联表中添加类型校验逻辑,或者在业务层判断。
方案优势
- 完全支持任意数量的输入输出,不用为不同结构的Recipe创建单独实体,扩展性拉满。
- 统一资源表后,避免了重复建表,降低维护成本。
- 符合关系型数据库设计规范,查询效率高(比如统计某个资源被哪些配方使用/产出)。
内容的提问来源于stack exchange,提问作者Lumi
相关产品推荐
相关产品推荐

