# Crossgate-魔力宝贝
## Unity C# 图档解析库
## 1、开源目的
本脚本旨在学习研究```Crossgate``` ```魔力宝贝``` 图档bin文件的解压与使用,相关资料来源于互联网文章与相关技术大佬指导
再次感谢```阿伍```等在互联网上分享相关解压、算法解析等教学文章的技术大佬所提供的帮助
本脚本遵照GPL共享协议,可随意修改、调整代码学习使用
请务删除或修改文档或源代码中相关版权声明信息,且严禁用于商业项目
因利用本脚本盈利或其他行为导致的任何商业版权纠纷,脚本作者不承担任何责任或损失
本解析库原始发布地址: [https://git.honorlee.me/HonorLee/CGTool](https://git.honorlee.me/HonorLee/CGTool)
同步更新至Github: [https://github.com/HonorLee-cn/CGTool](https://github.com/HonorLee-cn/CGTool)
如有任何问题请至Github提交Issues或联系作者
![预览](Preview/Preview.png)
## 2、功能支持
> 当前版本目前已支持 魔力宝贝3.7-龙之沙漏 及以下版本的图档解析,以及 4.0 版本以上图档、动画数据解析
>
> 注意:当前版本 4.0 及以上地图暂不支持
>
> 目前版本支持以下功能:
>
> * `GraphicInfo` [图档索引解析](#获取图档索引数据)
> * `GraphicData` [图档数据解析](#获取图档实体数据)
> * `Palet` 调色板数据解析
> * `Map` [服务端/客户端 图数据解析](#获取地图数据)
> * `Audio` [音频索引及加载](#播放音频)
> * `AnimeInfo` 动画索引解析
> * `Anime` 动画数据解析
> * `AnimePlayer` [动画播放器挂载组件](#动画播放)
> * `AnimePlayer` 动画关键帧(攻击/攻击完成)事件回调
> * `AnimePlayer` 音频帧事件回调
## 3、使用说明
### 基本环境
请确认Unity已安装以下Package包:
```
"dependencies": {
"com.unity.burst": "1.6.0",
"com.unity.visualscripting": "1.9.0"
}
```
克隆当前仓库或下载zip包解压,将 CrossgateToolkit 文件夹放置于Unity项目文件夹内引用
可直接下载Release中unitypackage直接导入
### 工具库说明
最新 V2.0 版本已移除对魔力宝贝原版本的强绑定,初始化程序将根据目标路径进行自动分析
规划图档目录结构时,图档根目录下建议以数字版本号方式命名不同版本图档子目录
CGTool在初始化时对所配置图档根目录进行扫描,并按照``根目录优先``、``子目录按字符排序``方式依次加载并初始化图档数据
所涉及的所有Index则为图档序号、Serial为图档或动画的具体编号而非索引档中序号,实际使用时请注意区分
其他相关部分会逐渐更新完善
### 框架初始化
在入口或初始化脚本头部引入CGTool初始化文件
```csharp
using CrossgateToolkit;
```
并在相关初始化位置对CGTool进行初始化
```csharp
// 配置Crossgate相关资源路径,如跳过则默认为 Environment.CurrentDirectory 下相关 目录
CGTool.PATH = new CGTool.CGPath()
{
// 调色板目录,不可省略
PAL = Application.persistentDataPath + "/pal",
// BIN图档目录,包含图档索引、图档文件、动画索引、动画文件等根目录
// 初始化时会自动便利查询分析所有文件数据,不可省略
BIN = Application.persistentDataPath + "/bin",
// 地图文件目录,省略则不对地图数据初始化
MAP = Application.persistentDataPath + "/map",
// 音频文件目录,省略则不对音频初始化
BGM = Application.persistentDataPath + "/bgm",
AUDIO = Application.persistentDataPath + "/se"
};
// 初始化
CGTool.Init();
```
CGTool初始化时,会自动对相关索引Info文件进行解析,请根据实际所采用版本情况,对脚本代码中解析相关的文件名称进行修改调整
### 获取图档索引数据
(图档基本索引数据属性信息)
```csharp
// 正常通过编号获取图档信息,无需版本号(常规图档)
GraphicInfoData graphicInfoData = GraphicInfo.GetGraphicInfoData(uint Serial);
// 通过索引获取图档信息,带版本号(特殊无编号图档获取,如动画获取每帧图档时)
GraphicInfoData graphicInfoData = GraphicInfo.GetGraphicInfoDataByIndex(string version, uint Serial);
```
### 获取图档实体数据
(图档实际数据,包含图像Sprite资源)
```csharp
// 直接通过编号获取
GraphicDetail graphicDetail = Graphic.GetGraphicDetail(uint serial,int palet = 0);
// 或 通过GraphicInfoData获取
GraphicDetail graphicDetail = GraphicData.GetGraphicDetail(GraphicInfoData graphicInfoData, int palet = 0);
/**
* 使用说明:
* 所有通过Graphic获取的图档Sprite均已做偏移处理,可直接使用
* 需自行判断图档是否存在,并处理图档不存在的情况
* 1.获取指定编号的图档索引信息
* 2.根据获取到的索引取得图档数据
* 3.使用图档数据中的Sprite资源进行绘制
*/
GraphicInfoData graphicInfoData = GraphicInfo.GetGraphicInfoData(Serial);
GraphicDetail graphicDetail = GraphicData.GetGraphicDetail(graphicInfoData ,0);
SpriteRenderer(Image).sprite = graphicDetail.Sprite;
```
### 获取地图数据
```csharp
// 通过编号获取地图数据,地图数据中包含地面及地上物件数据以及寻路用的二维数组
// 可自行阅读源码查询相关属性成员和使用方式
Map.MapInfo mapInfo = Map.GetMap(uint Serial);
```
### 图档合批
为减少渲染时的Drawcall和Batchs动态合批数量提高性能并降低内存消耗,工具库提供了大量图档合批(并)处理方法
图档合并时,会自动根据每个图档图像由小到大进行排序处理,以最大限度将多个图档合并至一个或多个稍大的Texture2D中
```csharp
/**
* 合批图档
* 通过指定图档序列,对图档进行合批处理,并返回合批后的图档数据
* @param graphicInfoDatas 图档索引数据序列
* @param palet 调色板序号
* @param maxTextureSize 单个Texture最大尺寸,地面数据建议2048,物件数据建议4096
* @param padding 图档间隔,可以有效避免图档渲染时出现多余的黑边或像素黏连
* @return Dictionary 合批后的图档数据,Key(unit)为图档数据编号,Value为图档数据
*/
GraphicData.BakeGraphics(
List graphicInfoDatas,
int palet = 0,
int maxTextureSize = 2048,
int padding = 0)
```
### 地图地面/物件图档合批数据
针对地图图档部分合批提供了相应的简化方法,可以酌情使用
```csharp
/**
* * 地面数据将拼合成一个或多个2048*2048尺寸Texture2D
* * 物件(建筑等)拼合成一个或多个不大于4096*4096尺寸Texture2D
* 另: 由于4.0后地图模式变动,部分地图图档过大,所以这个方法可能不适用于4.0后的地图
*/
// 地面合批
Dictionary MapGroundSerialDic =
Map.BakeGrounds( // <= 合并地面图形
List graphicInfoDatas,
int PaletIndex = 0
);
// 物件合批
Dictionary MapObjectSerialDic =
Graphic.BakeObjects( // <= 合并物件图形
List graphicInfoDatas,
int PaletIndex = 0
);
```
![地面合并效果](Preview/MapGroundMix.png)
![物件合并效果](Preview/MapObjectMix.png)
![资源合并后效果](Preview/batches.png)
### 播放音频
```csharp
CGTool.Audio.Play(AudioSource audioSource,Type type, int serial)
//播放背景音乐
CGTool.Audio.Play(AudioSource audioSource,Audio.Type.BGM,int serial);
//获取音效音频
CGTool.Audio.Play(AudioSource audioSource,Audio.Type.EFFECT,int serial);
```
### 动画播放
```csharp
/**
* 动画播放器,用于播放CG动画,支持多动画队列播放
* 1.3更新后已无需手动挂载SpriteRenderer、Image组件,程序会自动处理
* 只需将AnimePlayer挂载到任意GameObject上即可
* 可手动指定渲染方式是否以Image组件渲染
* 可选择是否对序列帧图像进行合批(建议开启)
*
* 动画解析Anime类中包含以下多个枚举预设:
* DirectionType 方向类型,含8个不同方向
* ActionType 动作类型,含20个不同动作
* EffectType 动作效果,含Hit和HitOver两种判定
* PlayType 播放类型,含Loop、Once、OnceAndDestory三种类型
*
* 当动画播放完成后会自动调用onFinishCallback回调函数
* 另外可指定onActionListener和onAudioListener监听动画动作帧和音频帧相关判定
*
* 目前已知的动作帧有:
* 击中 Hit (未结束攻击动作,如小石像、黄蜂、绿螳螂等单次攻击动作中有多次击中效果)
* 伤害结算 HitOver
*/
AnimePlayer player = GetComponent();
/**
* 播放动画,调用此方法将会清空当前播放队列,调用完成可通过链式调用nextPlay方法添加动画到播放队列
* @param Serial 动画序列号
* @param Direction 动画方向
* @param ActionType 动画动作
* @param PlayType 播放类型 Loop / Once / OnceAndDestory
* @param Speed 播放速度倍率,以 1s 为单位基准,根据动画帧率计算实际播放周期时长
* @param onFinishCallback 动画结束回调
* @return AnimePlayer
*/
player.play(
uint Serial,
Anime.DirectionType Direction = Anime.DirectionType.North,
Anime.ActionType actionType = Anime.ActionType.Stand,
Anime.PlayType playType = Anime.PlayType.Once,
float Speed = 1f,
AnimeCallback onFinishCallback = null
);
// 简化播放: 此方法大多数情况下用以播放特效动画,没有方向和动作类型
player.play(
uint Serial,
Anime.PlayType playType,
float speed = 1f,
AnimeCallback onFinishCallback = null
);
// 播放一次
player.playOnce(
Anime.DirectionType directionType,
Anime.ActionType actionType,
float Speed=1f,
AnimeCallback onFinishCallback=null
);
// 循环播放
player.playLoop(
Anime.DirectionType directionType,
Anime.ActionType actionType,
float Speed=1f,
AnimeCallback onFinishCallback=null
);
/**
* 可通过setter方法设置动画
* 通过setter方法设置的动画将使用以下默认配置
* DirectionType = DirectionType.North
* ActionType = ActionType.Stand
* PlayType = PlayType.Loop
* Speed = 1f
*/
player.Serial = uint AnimeSerial;
// 设置帧动效反馈监听
player.onEffectListener = effect => {...};
// 设置帧音效反馈监听
player.onAudioListener = audioIndex => {...};
// 链式调用添加动作队列
player.play(...params).nextPlay(...params);
// 动态修改动画所用的调色板索引
player.PaletIndex = int PaletIndex;
// 动态修改动画播放类型
player.PlayType = Anime.PlayType;
// 动态调整当前动画方向
player.DirectionType = Anime.DirectionType;
// 动态调整当前动画动作
player.ActionType = Anime.ActionType;
// 动画帧延时,动态修改当前动画,延长每帧之间的时间间隔(此方法定义有歧义,后续更新调整)
player.DelayPlay(float delayTime)
// 停止动画
player.Stop();
```
### 其他
请根据情况自行探索修改代码适应应用场景
## 4、更新日志
### v 2.5
> `FIX` Audio播放代码忘了补充
>
> `UPD` 加入BLiner过滤支持,可以在获取图档时获取对应过滤图像,同时对AnimePlayer增加Liner可选项
### v 2.4
> `FIX` 继续调整目录分析,处理部分特殊情况
>
> `FIX` 对于修改过的Anime进行适配,修复高低版本动画数据混合情况解析报错问题
### v 2.3
> `FIX` 调整高版本动画播放标记、翻转问题
### v 2.2
> `ADD` 增加 4.0 版本(乐园之卵)及后续版本图档、动画解析
>
> `UPD` 调整图档目录版本号分析过程,以更好的适应多种图档目录结构
### v 2.1
> `UPD` 图档合并方法进行统一处理,并增加地图相关简便方法
### v 2.0
> `ADD` 修改初始化方法以支持更复杂的图档文件建构
>
> `UPD` 图档解析支持多层目录结构并能自动识别加载,方便对图档进行扩充升级,建议根据版本号对图档子目录进行命名
>
> `UPD` 图档获取和加载方法优化,减少无用参数
>
> `UPD` 根据新的加载方式调整相关工具库代码以适应新的加载方式
### v 1.7
> `ADD` 加入地图物件合批处理
### v 1.6
> `ADD` 加入客户端地图读取支持,同时附加了客户端地图文件缺失的名字和调色版映射表
>
> `UPD` Anime合批处理图形之间增加间隔,避免出现像素黏连
>
> `UPD` AnimePlayer挂载件预留FrameTexture属性可在Editor中查看合批的图像
>
> `UPD` CGTool入口调整,可指定bin目录位置
### v 1.5
> `UPD` Anime序列帧合批忘了考虑不同调色板的问题,现已增加相关处理
### v 1.4
> `ADD` 加入Anime序列帧合批,挂载AnimePlayer后可手动设置是否开启合批(建议开启)
### v 1.3
> `UPD` 优化AnimePlayer组件的挂载和使用方式
>
> `UPD` 优化AnimePlayer动画播放器,增加动画相关处理方法
>
> `UPD` 更新README说明文档,增加、调整使用说明
>
### v 1.2
> `FIX` 修正文件加载时判断为正则,避免因使用不同版本bin导致加载报错问题
### v 1.1
> `ADD` 音频索引及加载AudioTool
>
> `ADD` 动画播放器添加对Image渲染支持,用以支持GUI动画播放
>
> `ADD` Graphic增加地面图档动态合批
>
> `ADD` Anime增加动画帧动态合批方法
>
> `UPD` 优化Graphic解析,统一改为RGBA4444模式,以减少内存占用
>
> `UPD` 重新整理初始化代码,优化初始化流程
>
> `UPD` 优化动画播放器,增加动画相关处理方法
>
> `UPD` 动画播放器添加对Image渲染支持,用以支持GUI动画播放
>
> `FIX` 修复动画序列中攻击判定、音频序列解析方式错误的问题
### v 1.0
> `ADD` 脚本初始化
>
> `ADD` 图档索引GraphicInfo文件解析
>
> `ADD` 图档Graphic文件数据解析
>
> `ADD` 调色板Palet文件解析
>
> `ADD` 动画索引AnimeInfo文件解析
>
> `ADD` 动画Anime文件数据解析
>
> `ADD` 服务端地图文件解析
## 5、待处理
- 支援 4.0 以上版本图档解析
- 其他未知
- 优化
## LICENSE
This project is licensed under the GPL license. Copyrights are respective of each contributor listed at the beginning of each definition file.