Unity3D 动作游戏开发日志自动化扩展数据库

Posted 大熊的日记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity3D 动作游戏开发日志自动化扩展数据库相关的知识,希望对你有一定的参考价值。

前言

这周做完了两件事情,一是捣鼓出了一套全自动化的数据库维护/更新/使用的框架,二是也制定和完善了游戏的系统框架。前者还算比较容易,因为有过不少处理游戏数据库的经验,再加上学习了工作室前几款游戏的后端代码,简单看了几篇讲规范的文章就瞎弄出自己的一套Database代码和维护系统。除此之外,剩下的时间都用来了研究游戏的系统框架上。


不同于之前写的针对角色的框架,系统框架更多层面上代表了整个游戏的信息交流和数据获取的规范和模式,例如上一篇提到的Singtelon也是其中的一种。但Singtelon在我看来始终是一种"作弊"性质的工具,它的最好的归宿也只能用是快速迭代或者Game Jam上面了。一个Properly Planned的系统框架在我看来是不需要用到Singtelon的,比较自豪的是这几天我成功瞎捣鼓出了一个完全不需要Singtelon,基于Event 并且Loose Couple & Extendable & Debuggable的系统框架,下周会和大家分享我的设计心路历程。这周就决定跟大家分享下我的数据库和存档的管理经验,毕竟我设计的系统框架也是基于在这套数据库系统之上的。



基础设计

整体的框架思路很简单:数据库方面用Excel来存储数据,导出成csv放进Unity然后用插件CsvHelper来将其转化为游戏内的数据;玩家存档方面则是简单的用Json来处理。


Unity3D 动作游戏开发日志(八)自动化扩展数据库


当然这都是一些很常规的搭建后端数据的操作,也没有什么值得讨论的地方。提起这个的原因就是我在浏览之前项目的代码时,发现负责项目的程序员给后端的每一类数据都单独写了一个Get/Set以及初始化的Process函数。


举个例子,我的数据库里有两类数据,一个数据是ItemData,该数据记录了游戏里的所有物品的数据,另一个则是EnemyData,相对应的它包含了游戏里所有敌人相关的数据。但又因为两类数据都是各自以系统的Collection(例如List)的形式来保存,那么就会造成一个问题就是每次我想尝试往数据库里添加进新类的数据时,我需要首先写处理该类数据的函数ProcessData,即把该数据从Json/XML导入成能够从代码里直接访问的类,然后我还需要在手动实现该数据的Get/Set类等等。


但是其实这些Get/Set 和 ProcessData 的函数都大体相近,为什么要每类数据都要单独写的原因是因为他们是的数据是单独存放在一个Collection里的,而不同的Get/Set函数其实也就只是从不同的Collection里面获取数据而已。(如下图)

Unity3D 动作游戏开发日志(八)自动化扩展数据库

当然了,这个问题也很容易解决,我们只需要让ItemData和EnemyData都继承于RawData类,然后用让开发者在使用Get/Set时都必须提供Generic Type,我们在根据Generic Type去建立一个Get函数来搜寻相应的Collection就能解决上述问题。

Unity3D 动作游戏开发日志(八)自动化扩展数据库

根据Generic Type来搜寻相应的Database有很多种方法,在这里我是直接将Generic Type转换为String然后来搜索Database的。

Unity3D 动作游戏开发日志(八)自动化扩展数据库

但是这样一来我们就需要将所有类型的Database储存在同一个Collection里然后再用关键字来进行搜索,在一个Collection里储存不同Type的方法其实很简单,在这里我就直接挂图了:

Unity3D 动作游戏开发日志(八)自动化扩展数据库

这样一来,我们就会有Table<EnemyData>和Table<ItemData>,想获取其中一个Database我们只需要根据关键词找到对应的Table然后返回即可。

Unity3D 动作游戏开发日志(八)自动化扩展数据库



一些小改进

这样看来上述的问题似乎被解决了:我们不需要再针对每一类数据去建立一个专门的Get/Set函数了。但是到目前为止我们还依然没有解决ProcessData的问题:在系统里根据系统的数据类型去搜寻对应的数据类型的数据其实不难办到,因为整个过程都发生在系统内;但是我们从硬盘里读取XML的时候我们并不知道这个文件对应的是系统里面的哪一种数据类型(除非我们手动Reference该数据进系统),那这样就还是会导致我们每次往系统里加入新的数据,我都需要手动Reference该文件进系统来告诉系统这对应的是什么数据类型。


但是我们既然都已经让Get/Set能自动处理了,我们为什么不能让这一部分也能自动处理呢?


解决方法也很简单,我们只需要让每个类数据对应的文件的命名与其对应的项目内的类相同就好,例如包含着ItemData的文件就应该叫ItemData.csv。然后我们只需要一次性异步加载好所有的csv,然后在根据文件名找到对应的class就好。


但是问题也出现在在这一部分,根据文件名转换成系统的Type很简单:

Unity3D 动作游戏开发日志(八)自动化扩展数据库

但是将系统Type转换成Generic Type却很难实现,在这里查了好几个小时的资料,最后还是成功的用系统的Reflection库解决了。

Unity3D 动作游戏开发日志(八)自动化扩展数据库

下图是对应上图的"ProcessRefText"。

Unity3D 动作游戏开发日志(八)自动化扩展数据库

数据库的设计和规划大致就是这样,玩家存档方面则没有太多好讲的,因为玩家的数据是既需要从文本数据转换成系统数据来读取,也需要能够从系统数据转换回文本数据来保存(系统数据库只需要能读取),所以对数据库的操作并不能直接对玩家存档使用,我们就简单的用Json来保存/读取数据就好。但是为了让playerData也能实现一键Get/Set,我在玩家的playerData里HardCode了每个类数据对应的Id进一个Reference List,然后Get/Set时根据这个Reference去获取数据就好,之后更新玩家的Data类也只需要去更新这个Reference List就好。

如此一来,我们就完全实现了数据库的“自动化”扩展,往后比方要加入什么DungeonData或者WeaponData,我们只需要将csv放进项目创建相应的类数据的class就行了,可以说是特别的方便。但是这里比较慌的是我又在项目里引入了一个新的库,但是我却并不知道这个库对移动平台和家用主机平台的兼容性如何.. 例如坑爹的Nintendo Swtich就不兼容很多Net库,但是我想了想,要是Relection库不被支持,我大不了直接Hardcode把文件转换成Generic Type不就好了,于是我也心安理得的commit了。



题外话:上上周Unity的Addressable System (AS)正式脱离preview version,但是还是有很多问题,直到上周更新了1.1.10版本才修复了一些坑了我很多次的Bug,我也正式的将项目转去Addressable System。不得不说Addressable是真的比Asset Bundle (AB)好用一万倍,都不需要自己去手撸各种管理打包和加载热更新资源包的代码了,但是缺点就是这个系统比较新,没有像AB那样已经形成了一套完整的Work Flow,并且AS对应的Documentaion比较少,很多东西都只得自己去排坑和搭建一套Work Flow,之后要是瞎捣鼓了什么觉得可以的工作流水线就跟大家分享下。




以上是关于Unity3D 动作游戏开发日志自动化扩展数据库的主要内容,如果未能解决你的问题,请参考以下文章

《Unity3D动作游戏开发实战》笔记及扩展2.1

unity3D游戏开发实战原创视频讲座系列11之相扑游戏开发并公布到WinWp8

Unity3D外包(u3d外包)—就找北京动点软件(我们长年承接U3D外包Maya3DMax项目外包)

unity中人物为什么会自己动

unity3d 插件是啥

Unity3D外包