欢迎参与讨论,转载请注明出处。
  本文转载自https://musoucrow.github.io/2018/01/20/dnf_mobile_ex/

前言

  《DNFMobile》的新一波内测到来了,恰好得到了安装包。便欲对比其资源较之端游有何不同,遂试图提取之。在尝试的途中遇到了不少问题,特此记录之。源码地址

读取资源包

  与众多手游的习惯一样,初始的安装包所携带的资源甚少,皆需经过更新方才完整。更新后经过观察得知游戏采用Unity制作,那么事情便简单了,直接上UnityStudio读取。虽然资源文件的后缀名为.npk,但实际上则是Unity的AssetBundle,且并未作加密。然而诸多现成的Unity提取工具皆有多少缺陷(无法识别pvr格式、无法批量化操作、导出资源过于原始等),且图片资源是大图形式存在的,需要进行切图,而使用切图工具一则怕不够精确,二则怕无法批量化。于是我选择直接使用Unity制作工具以面对此需求。
  由于资源文件本身即是Unity的格式,那么直接调用API加载即可,类似如此:

var assetBundle = AssetBundle.LoadFromFile(path);
var assetBundle.LoadAllAssets<Texture2D>();foreach (var tex in texs) {//...
}

切图

  这样可谓相当方便,接下来的问题便是切图了。我本以为大图是由Unity自动生成,所以理应资源内会有对应的Sprite资源,这样通过Sprite资源的信息即可进行切割。但实际上并非如此:大图是事先生成好,然后使用脚本填写每帧配置在运行时自动生成Sprite。这种做法也是理所当然的,毕竟Unity的Sprite的pivot与DNF的IMG包提供的偏移点可谓天南地北。(一者为当前图片下的浮点百分比,另一者为实际坐标)通过直接在配置直接对接IMG包的数据然后进行转化这是很正常的做法。可这下子就麻烦了,我们并无法直接知道这脚本的具体信息。幸好UnityStudio的解析中包括了关于MonoBehavior资源配置的信息。

  可即使知道也无法直接Unity进行获取,毕竟我们本身是没有该脚本的。鉴于UnityStudio开源的特性,我起初打算阅读源码掌握其解析之法。最后也成功了,可我突然脑内灵光一闪,想到了直接建立一个同名脚本,并根据配置的信息进行模拟。代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DNFAtlasAsset : MonoBehaviour {[Serializable]public struct Rectf {public float x;public float y;public float width;public float height;}[Serializable]public struct DNFAtlasElement {public string name;public int originIndex;public int referenceIndex;public int originWidth;public int originHeight;public int offsetX;public int offsetY;public Rectf rect;}[Serializable]public struct DNFAtlasSlot {public int matType;public DNFAtlasElement[] elementList;}public string atalsName;public DNFAtlasSlot[] atlasSlotList;
}

  天可怜见,居然成功了!那么接下来采用类似如下方法即可:

int width = (int)element.rect.width;
int height = (int)element.rect.height;if (width == 0 || height == 0) {continue;
}var colors = tex.GetPixels((int)element.rect.x, (int)element.rect.y, width, height);
var newTex = new Texture2D(width, height, tex.format, tex.mipmapCount > 1);
newTex.SetPixels(colors);
newTex.Apply();var path = this.GetPath() + tex.name + "/";
var bytes = newTex.EncodeToPNG();
var json = JsonUtility.ToJson(element);
var name = this.ToNumber(element.name);this.CreateDirectory(path);
File.WriteAllText(path + name + ".json", json);
File.WriteAllBytes(path + name + ".png", bytes);
Texture2D.DestroyImmediate(newTex, true);

  主要思路便是通过GetPixels方法读取区域像素并覆盖至新图。最后将图片转换为PNG、配置转换为JSON并输出即可。
  当然这里还有关于Texture2D的readable问题,隶属于资源包的Texture2D并无法直接使用GetPixels方法,需要对其进行复制,然后利用新图施为,为此我写了个函数:

private Texture2D GetTexture(Texture2D tex){if (!this.texureMap.ContainsKey(tex)) {if (tex.width == 0 || tex.height == 0) {return null;}var copyTex = new Texture2D(tex.width, tex.height, tex.format, tex.mipmapCount > 1);copyTex.LoadRawTextureData(tex.GetRawTextureData());copyTex.Apply();var writeTex = new Texture2D(copyTex.width, copyTex.height);writeTex.SetPixels32(copyTex.GetPixels32());writeTex.Apply();writeTex.name = this.ToName(tex.name);this.texureMap[tex] = writeTex;Texture2D.DestroyImmediate(copyTex, true);}return this.texureMap[tex];
}

  以上便是关于切图方面的问题,具体可参阅源码。

内存问题

  游戏目前的资源包数量高达2900以上,在尝试一口气全部提取时内存竟然高达5G!最终电脑不堪重负倒下收场。这很显然是资源并未回收所致,是以作此函数:

public void Destroy() {foreach (var texture in this.texureMap) {Texture2D.DestroyImmediate(texture.Key, true);Texture2D.DestroyImmediate(texture.Value, true);}this.texureMap.Clear();this.assetBundle.Unload(true);AssetBundle.DestroyImmediate(this.assetBundle, true);
}

  这里采用的是DestroyImmediate方法,好处是立即进行回收,但却会因此阻塞,影响提取效率。若使用Destroy方法则不会如此,不过峰值内存会上升。但大规模读取时还是以稳定为主,而小份读取则两者并无所谓。是以选择DestroyImmediate方法。
  另外在其他地方涉及到资源生成且是继承自UnityEngine.Object的,皆需注意此问题。在经过优化后,占用由5G跌倒了500M-1.5G之间,成功提取了全部图片资源。大功告成!

后记

  这次《DNFMobile》的声音资源经过了高压,原本几M的音乐变成了上百K,可谓惨不忍听,遂无提取的价值。而纸娃娃方面则是采用了类似NPK_Ver4的色板做法,也并无法直接提取到成品。由此可见制作组为了节省空间可是下了不少功夫呀。

《DNFMobile》图片资源提取笔记相关推荐

  1. iphone ipa图片资源提取

    提取方法:http://bbs.weiphone.com/read-htm-tid-1408073.html 我是windows xp,先把ipa软件后缀改成zip,然后用winrar解压,然后下载i ...

  2. 将 Citavi 笔记按需要导出

    Citavi 的笔记功能相比其他文献管理软件较为完善,对 PDF 的标注是一种双链标注,阅读论文更方便,这也是当下很多笔记软件在做的功能之一: Logseq 相关介绍:PDF highlights ( ...

  3. iBackup Viewer for mac(iPhone备份提取工具)

    iBackup Viewer是免费的iPhone备份提取,浏览和管理备份.iBackup浏览器帮你管理,以提取iPhone / iPad的备份信息. 作为备份提取iBackup浏览器,它很容易保存Ma ...

  4. Java GUI 贪吃蛇小游戏项目实战含图片资源

    项目实战 - 贪吃蛇 图片资源提取地址 百度网盘 链接:https://pan.baidu.com/s/19gEhIuZrut12l5a8jcknFA?pwd=1111 提取码:1111 界面绘制 这 ...

  5. iBackup Viewer for mac一款好用的(iPhone备份提取工具)

    通过iTunes应用程序,您可以快速备份存储在iOS设备上的内容,例如iPhone,iPad或iPod touch.iBackup Viewer是一款简单的Mac应用程序,可让您访问存储在这些备份中的 ...

  6. Wallpaper引擎 壁纸提取 (文中附工具下载链接)

    有一款优秀的电脑桌面壁纸软件--<Wallpaper Engine> 用过的都知道,好得不得了 但是,这款壁纸软件还是很吃GPU的,尤其是场景类.视频类的壁纸,电脑性能不足的还会卡可怜的笔 ...

  7. 文学电子文献制作与使用 操作笔记

    目录 姓名编码 论文排版 书签制作 PDF/A 双图层文档制作 第三次大作业 -- <全清词·雍乾卷>目录提取 笔记说明:!!!本笔记完全供自己和同学使用!!!请勿过分转载!!! 建议全看 ...

  8. [5-23]绿色精品软件每天更新[uc23整理]

    [5-23]绿色精品软件每天更新[uc23整理] 温馨提示: 1:此更新合集由uc23热心整理,请直接点击下载或用下载工具下载. 2:由于某些下载站采用防盗链设计,请使用右键迅雷下载. 3:以下所有软 ...

  9. Zotero6.0来了,内容丰富,适合初学者(插件安装,翻译器更新)

    目录 zotero 6.0强势来袭 安装链接,以及插件分享 6.0新功能 PDF注释 插件安装以及使用 插件安装: 插件使用: 安装浏览器插件,并更新其翻译器(可以实现抓取博士论文等) 安装浏览器插件 ...

最新文章

  1. 用Leangoo看板进行可视化的缺陷跟踪管理
  2. dom4j 使用总结
  3. 计算机电缆数字是什么意思,DJYPV4*2*1.0 计算机电缆规格含义
  4. python安装在什么系统下最好-windows系统下Python环境的搭建
  5. 【ARM】ARM其它指令
  6. 随机函数rand()算法
  7. ubuntu安装redis 详细步骤
  8. HDOJ2072解题报告【字典树】
  9. strictmath_Java StrictMath ceil()方法与示例
  10. vue-router中hash模式、history模式原理
  11. windows 安装msi 出现报错 2503 无权限 使用cmd模式安装
  12. 解决Sublime Text 3在GB2312编码下的中文乱码问题
  13. windows下 apache配置rewrite错误解决
  14. 深入浅出SQLITE3
  15. 第五次课堂总结——付胤
  16. AE关键帧动画基础概念
  17. 一套MES系统需要多少钱?如何使生产管理系统标准化?
  18. python把日期数据转换成数字_python3时间datetime如何转换成数字?
  19. Sharding Sphere ~ Sharding-jdbc分库分表、读写分离
  20. correl函数相关系数大小意义_Excel使用Correl函数返回相关系数并确定属性关系的步骤方法...

热门文章

  1. 用Python实现ModbusTcp协议
  2. 妈,我又加班熬夜了,这次我真想你了
  3. 让您感动感悟一生的话语!
  4. 【ARM Cache 入门及渐进四 -- 乱序执行】
  5. 用matlab设计病态系统,SS04_病态系统仿真.ppt
  6. Android App 开发的三种姿势 ~
  7. 怎样下载安装python编程软件3.85_【咋】_咋字的读音|咋的意思
  8. 图像处理与机器视觉 综合课程设计
  9. 约瑟夫双向生死游戏c语言代码,约瑟夫生死游戏(含源代码可以运行)本科毕业设计.doc...
  10. GLSL实现Glow效果