本帖是延续的: C# Unity 游戏开发 Excel 中的数据是如何到游戏中的 (三)
前言
最近项目不算太忙, 终于有时间更新博客了关于数据处理这个主题前面的 (一)(二)(三) 基本上算是一个完整的静态数据处理方案了
不过前几篇发布的时候是 2015 年, 比较早了, 随着这几年技术不断积累和进步, 其实已经有更好的方案来处理数据了, 不过对于前端存储的那几个 M 的数据, 多点少点其实影响也不大
但是也不能就这样算了, 毕竟技术的变化日新月异, 还是要保持持续学习的心态
虽然简单但却不易忽视
对于游戏中静态数据的处理, 单纯的对于整个程序项目来说其实只是很小的一部分写个读写工具, 打个包, 压个缩, 加个密其实对于很
多程序来说也不是难事但是, 我又要说但是了但是, 根据博主的个人经验来说, 数据对于游戏的业务逻辑是非常底层的逻辑, 对于
后期的开发起到了一个基础的作用主要体现在两个方面:
1. 业务逻辑角度的数据结构化
这点很关键, 策划想要把自己大脑里的游戏玩法用数据表示出来, 而这个表示过程其实是需要程序配合的, 因为不可能每个策划
都那么牛逼, 然而现实情况也确实如此因此, 这部分要做的事就是, 用数据抽象的思维把策划描述的游戏世界表示出来, 最终
体现就是表格这些数据, 其实就是游戏业务逻辑的骨架, 后续的开发都是围绕着数据来做的, 或者说被数据支配的
2. 程序结构的设计
第一条说过了, 后续的开发都是围绕着数据来做的, 那么这些数据的使用频率必然会很高那么, 问题来了, 如何设计这部分的程序结构会使开发效率和运行效率最优? 单纯的创建一个类, 把所有数据查询的方法都放里面? 还是根据第一条抽象出来的实体类来组织数据, 然后对数据做一些预处理, 例如游戏运行先进行分类然后放到内存中等待使用?
显然, 后者更加高效, 这也静态数据处理虽然简单, 但是也不容忽视的理由
最新的方案
前面也说了, 技术是不断在变化的, 我们也需要快速适应之前的方案确实用了很长时间, 也没什么问题但是自己撸的代码总有几个疑问? 这是最好的方案吗? 和最好的方案差距有多大?
带着这几个问题, 在最近 2 年所做的项目中也对这方面做了一些工作: 1, 在最近的项目中使用了 ScriptableObject 的方式 2, 开始了一个 protobuf 方式处理数据的开源项目
说起来惭愧, 其实结果影响并不算很大, 下面把这部分总结一下
方案一 : 使用 Unity 的 ScriptableObject
做法就是每个表格生成的数据类都直接或者间接的继承自 ScriptableObject 类, 打包的时候直接把所有表数据都生成一个对应类型的. asset 文件然后建一个总的 Map 类来存放所有 asset 的引用, 当然这个 Map 类也必须继承自 ScriptableObject, 也生成对应的. asset 文件最终打包的时候, 只打这个 Map 类的. asset 文件, Unity 会自动识别里面的依赖关系, 将所有数据打包进 bundle
实体类 Hero
- using UnityEngine;
- public class Hero : ScriptableObject
- {
- public string name;
- public string level;
- }
Map 类
- using UnityEngine;
- using System.Collections.Generic;
- public class Map : ScriptableObject
- {
- public List<Hero> heroList = new List<Hero>();
- }
最终在使用的时候也很方便:
- AssetBundle bundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/constance");
- Map m_Constance = bundle.LoadAsset("constance") as Map;
这种方式对 Unity3D 非常友好, 使用起来也非常方便, 但是缺点也是有的, 下面来总结一下:
优点:
可以和预制产生依赖, prefab 如果依赖了 asset 打包的时候也会打进去, 减少了查找操作
可以直接用 Unity API 操作 asset 省去了一部分序列化反序列化代码
可以直接用 AssetBundle.LoadAsset() as Map; 加载, 省去了之前的反序列化代码
在 Unty 中选中 asset 可以直接在 Inpector 中看到数据
缺点:
生成 asset 的时候会有大量的文件操作, 速度慢
还有两个指标就是运行速度和存储空间由于影响不大, 没有做进一步测试
存储空间的话, 我这里有个参考: 6 个 Excel 文件占用的 pc 上的磁盘空间是 112k, 最终打成 AssetBundle 是 31k
方案二 : 使用 protobuf
这种做法主要是通过 google 提供的 protobuf 来序列化和反序列化数据, 并且使用 protoc 生成目标语言的代码工作流程如下图所示
把做法分成几部分来说:
操作 1, 读取 excel 数据描述信息, 通过 excel 数据描述信息生成. proto 文件
操作 2, 使用 protoc 命令行生成本地代码, 也就是你制作工具使用的语言代码
操作 3, 创建本地代码的类的实例
操作 4, 读取 excel 数据, 并且将内容赋值给操作 3 创建的实例, 最终使用 protobuf API 序列化
操作 5, 生成目标平台的代码
最终生成的二进制文件 (.bytes) 和目标代码会和程序一同发布, 使用生成的目标代码解析生成的二进制数据
具体代码就不贴出了, 下面是本人对方案二开启的一个开源项目, 用的是 java+netbean8.2, 目前已经完成大部分内容
有兴趣的同学可以看一下我会一直更新
https://github.com/superbig/GearDataExporter
最后
如果你在游戏开发的静态数据处理方面还在犹豫, 建议是: 如果项目小可是试试 ScriptableObject 方式, 应使用起来确实要方便一些当然你也需要忍受数据导出时候的频繁的 IO 操作(当然其实你也可以开发一个增量导出的工具)
如果项目大, 数据很多还是老老实实用 protobuf, 空间占用少, 速度快或者自己写
来源: https://www.cnblogs.com/fly-100/p/8707749.html