《江湖X》开发笔谈 - 谈谈配置表的那些事

大家好,我是汉家松鼠工作室创始人cg,今天我们来借我们开发中的游戏《江湖X》,来工程化的谈一下配置表以及它引申出来的各种概念。(我们本文只讨论游戏开发技术、管理,不讨论具体的游戏内容设计。)

这里写图片描述

江湖X虽然是一款独立游戏,但我们在系统框架级别,希望它是一个能够容纳项目团队扩展乃至未来作为我们所有游戏引擎框架的一个模板。简而言之,我们希望实现一个完整的配置表打包体系,并且融入到我们整个项目,贯穿了开发、测试、发布、运维等各个流程。目前来看,我们确实在技术层面做到了(虽然还有许多地方需要优化,但总体达标)

在此,我详细的介绍一下我们在设计之初的思考点和遇到的坑。

我们定位《江湖X》是一个需要长线运营,需要能够高效、快速的填充游戏内容,而又需要策划易于上手,容易测试。所以我们在系统架构上需要保证和思考几点:

  • 如何写出一个强大、高效的配置表程序?让后期尽量我们不需要去维护打包程序,而具备我们想要的复杂数据结构打包功能?
  • 如何保障策划和程序员各司其职,能够有序的在项目中协作?
  • 如何保障许多名策划协作工作,而互相影响降到最小?如何保障策划们独立分工,如何管理一个完整的RPG项目中所有的资源?
  • 如何在此机制下实现热更新,如何来管理我们的版本?

先说一下我们目前的使用效果:

  • 4人(其中3人写代码+策划,1人美术)开发团队把游戏框架做出来;
  • 目前在完全没有动框架的情况下,扩展到 4程序(全部兼策划)+3策划+1美术 较高效协作开发;
  • 在没动框架情况下,运营游戏4个月,没有出过大的技术问题和瓶颈;
  • 我们有信心在不大动框架的情况下,扩展到20+人团队高效协作开发;

不能说有多出色,但基本实现了我们最初的构想和规划。接下来,我们开始谈谈各个模块我的设计思考历程

配置表

先解释一下什么叫配置表

在游戏设计中,有大量的内容填充的东东(比如有多少个角色;多少个技能,每个技能的攻击模式是什么、攻击力多少、成长多少;多少种物品等等)
这些东西如果写死在程序中,则会造成
1、程序难以维护和扩展(hardcode..有多么恐怖,程序员都知道)
2、难以集中管理所有的资源
3、策划难于上手(需要了解程序的语法)

所以一般很多游戏开发团队的做法是,用excel排表、填数据,再用程序去解析。我们称这些excel叫配置表。
那么在游戏开发中,程序和策划就可以用这个表切分,程序员来实现逻辑解析这些表,并且在游戏内用逻辑关联起来。游戏策划专注于表的设计、内容填充。

在顶级的公司或团队,大多是开发一个专门“地图编辑器”来实现此类功能(比如startcraft、warcraft的编辑器)。当然,这个的开发代价和成本不是简单的配表程序可比的……

我的理解,其实配置表就是一个游戏的静态数据库。它保存了游戏的基础内容,并且各个表之间实现了大量的逻辑关联。使用excel的原因是:
1、直观化编辑,提高策划开发效率;
2、能够方便的做数据分析(excel的各种公式、报表等)
3、入门门槛低
4、SVN/github等管理起来方便,和代码一起关联存

网络上确实有许多开源的配置表打包程序,而我们工作室根据自己的需求,独立实现了一套我们自己的配置表框架。有如下特性:

  • 有一套独立的XML语法定义excel的映射关系
  • 支持excel绑定到XML
  • 支持绑定到C#的Pojo,支持复杂数据结构定义(实现了ORM功能)
  • 支持到XML的增量打包
  • 支持拆分excel表
  • 支持打包protobuf(性能最高的序列化/反序列化库)
  • 开发环境支持跨平台(mac/windows)
  • 客户端运行平台支持跨平台(ios/android/pc…)

我们计划实现但目前尚未实现的特性:

  • 开发环境热配置(不需要重新打包,即可在开发环境中读取修改,方便策划人员编写和调试)

而我们确实使用此套程序在打包客户端、服务器所有相关配置表。
我们考虑在未来开源此套程序

我们最终的一键打包/程序读取后台流程如下:

excel -> xml -> [Deserialize]C# Pojo -> protobuf -> data文件 -> [Runtime]C# Pojo

下面给出一个我们的绑定语法例子大家可以看一下

<?xml version="1.0" encoding="utf-8"?>

<bean name="explore_event" from="T探索地图事件.xlsx" to="explore_events.xml" >
    <variable name="tag" fromCol="TAG" type="string" />
    <variable name="map" fromCol="所属地图" type="string" />
    <variable name="type" fromCol="类型" type="int"/>
    <variable name="story" fromCol="剧情" type="string" />
    <variable type="collection" fromCol="触发条件" split="\n">
        <bean name="condition" split=":">
            <variable name="type" notNull="true" fromIndex="0" type="string" />
            <variable name="value" fromIndex="1" type="string" />
        </bean>
    </variable>
    <variable name="number" fromCol="刷出次数" type="int" defaultValue="1"/>
    <variable name="locations" fromCol="刷出地点" type="string"/>
    <variable name="property" fromCol="概率" type="int" defaultValue="100"/>
    <variable name="image" fromCol="缩略图" type="string"/>
    <variable name="active_on_start" fromCol="开场刷出" type="int" defaultValue="0"/>
</bean>

这里个描述文件,描述了我们的excel映射关系。T探索地图事件.xlsx被打包成explore_events.xml形成名为explore_event的pojo。
里头关于各项属性,见具体描述,fromCol是来自具体excel的哪一列,可以定义类型(type)、默认值(defaultValue)等。
此外我们还可以定义collection类型,其也可以是一个自定义的pojo,具体语法细节此处不再赘述。

让程序和策划有序

或许一些独立开发者不会注重分工,因为团队只有一两个人,无所谓分工和工作切面。但我的建议是,工程化的管理是必要的,哪怕只有自己一个人,也应该严格区分几个工作模块。(用方法把自己的策划类、程序类、美术类等工作区分开来)

这是为了项目未来扩展和增长,也是用切面强迫自己遵循开发原则。

如何让程序和策划们有序的工作起来,这里其实已经到了一个我们的开发工艺流程的问题。这里仁者见仁,我仅谈谈我们的方法。

我的核心思想还是:

程序来实现编辑器,策划是编辑器的使用者。也就是说,策划是程序员的用户。

具体开发流程:
1、大家一起开脑洞,讨论游戏功能
2、偏策划的模块,由策划写需求文档,设计配置表结构(比如XXXX系统玩法)
3、偏程序的模块,由程序写需求文档,设计配置表结构(比如XXXX打击感增强模块)
4、策划填表、程序开发逻辑
5、程序编写逻辑代码和开发策划所需的测试工具(我们使用统一的控制台指令)
6、代码提交SVN
7、策划取代码,测试配置表,提交
8、打版工程师从SVN上取代码和配置表,打包发布

我们在unity中实现了一个小的控制台面板,用于测试开发和我们自己调试。由程序提供各项的测试控制台指令

这里写图片描述

如上图,下半部分放的是我们一些常用的指令集,每个人都可以根据自己的需要灵活配置。

让策划之间有序

使用excel在SVN上管理有一个比较麻烦的地方,使用csv模式的话不够强大(如不能使用公式、图标、表格格式等功能),但是可以做代码的merge。使用xls默认的格式的话,我们目前没有找到好的merge方法。

再说即使能够merge,我们也不希望。因为策划的工作是很独立,需要独立测试和考核的。大家如果经常混编一块资源,很容易造成极大的项目管理混乱。

所以我们的做法是:

将每个策划独立拆分一组excel。举个例子,每个我们把物品表,根据不同的策划人员,拆成了多个文件,最后打包的时候统一。这样每个人可以编辑自己的部分,而不影响其他人。不同的策划人员,也可以根据分工不同,给不同的权限。

对于一些必须公用的或者重要的excel,我们设置必须svn lock才可编辑。

或许会有人问,为什么要搞得这么麻烦?不会损失工作效率么?
——没有办法,我们认为这个地方笨的办法就是最好的办法,千万不能取巧。策划的配置表是个极其严谨的事情,必须责任到人。特别是游戏进入到运营状态后,严格的管理能够省去无穷多的后患。经验之谈!

关于版本运维

游戏发布了以后,需要更新版本。我们分“大更新”和“热更新”。

大更新(版本更新)也就是整个游戏包的更新,对应苹果的是ipa、安卓的是apk。
热更新(小版本更新)也就是游戏内更新,玩家可以进入游戏后下载新包。

大更新不用提了,直接使用unity打包测试提交。
我们这里主要讨论小版本的更新及版本管理方式,在设计的时候,有几个问题需要思考:

  • 哪些内容需要热更新?怎么做到?
  • 需要了解平台的约束,哪些东西是不能热更新的?
  • 小版本号之前是增量更新还是全量?
  • 大版本和小版本之间的差异如何来管理?

几个前提需要知道:

  • unity的assetbundle所有含有C#代码的部分,在ios平台上均不能加载。(ios平台的保护机制)
  • 目前的国内的CDN流量费用一般是0.3元/GB

那么我们的做法是:

1、增量图片资源部分:每次大版本既有资源(包括原来所有的热更独立资源)打图集,随包一起发布。热更部分,如果有新增的话,打assetbundle独立发布。

举个例子,我们所有的物品图标,为了降低drawcall,统一打包成图集,随包体发布。但如果我们需要临时增加一个物品A,我们则把它单独打在名为item的assetbundle包里热更发布。我们的热更新框架,将保证在程序层面其和原有的图集被一致的读取,对于策划人员来说,此项透明。

2、增量音乐/音效部分:直接使用assetbundle打包下发
3、配置表/LUA等:每次完整打包、全量下发

这样做的目的是,我们需要在某个大版本下打包热更新,则只需要把配置表和相关的lua代码到当时的打版代码下,生成即可。主要原因有以下几点:
1、protobuf必须保证原生数据结构不发生改变
2、全量在客户端读取方更好管理,而且我们算下来也只有压缩后不到2MB的更新数据,CDN费用可以承受
3、降低我们的运维复杂度,运维人员永远只需要维护一份最新的更新包,而不用管历史的

4、副本/地图配置等:每次完整打包、全量下发

同上,占用数据不大,为了方便运维管理,都是全量。

对于本块热更新如果有人感兴趣的话,我将回头另外写一篇笔谈,专门讨论热更新框架的代码层面,如何比较优雅的实现对客户端程序员和策划的透明化。

结语

诚然我们的这些东东都很稚嫩,但确实是在开发和运营过程中摸索出来的。我们也会一直不断的去完善它,作为一个框架性的生产力工具,将会贯穿我们未来的每一款制作游戏中。

当然,工程化和创意其实也是有隐性对立关系的,如何保证优秀的创意能够工程化的方法实现出来,也是一种艺术,不是么?

最后,欢迎大家与我交流!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值