使用场景
我们都知道unity的资源导出是导出成.unitypackage文件,如果要里面的内容,得打开Unity,将unitypackage导入进去才能看到里面的内容。
但是很多时候我们下了几十个unitypackage资源包,又不清楚好不好用,而且导入之后编译特别慢,unity又不提供批量解压的功能,所以这时候就想能不能提前解压呢。
当然可以,为此我做了一个工具,可以不需要unity直接将unitypackage解压出来,这里我介绍下他的用法,后续我会把工具包上传上来。
工具包内容如下:
使用说明
这个工具包是用C#写的,我先说下说用方法:
- 单个解压:适用于只解压一个unitypackage的情况
@echo off ::设置unitypackage文件路径 set fileName=file.unitypackage ::设置导出目录 set destPath=file call dotnet-ExtractUnityPackage.exe %fileName% %destPath% echo 导出成功! pause
运行前先修改下fileName也就是.unitypackage的路径,destPath就是导出目录
修改完毕双击直接运行即可 - 批量解压:适用于解压文件夹下包括子目录下的所有unitypackage文件
将多个unitypackage文件复制到sources目录下,双击批量解压.bat,即可在export里找到解压出来的内容
程序原理
主要代码
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
using System.IO;
namespace ExtractUnityPackage
{
internal static class Extractor
{
public static void ImportUnityPackage(string packagePath, string destinationFolderPath, bool overwrite)
{
var tempFolder = Path.Combine(Path.GetTempPath(), Path.GetFileName(packagePath) + ".unitypackage.extract");
using (var i = new FileStream(packagePath, FileMode.Open, FileAccess.Read))
using (var gi = new GZipInputStream(i))
using (var tar = TarArchive.CreateInputTarArchive(gi))
{
tar.ExtractContents(tempFolder);
}
foreach (var item in Directory.GetDirectories(tempFolder))
{
var pathNameData = File.ReadAllLines(Path.Combine(item, "pathname"));
var pathname = pathNameData[0];
var path = Path.Combine(destinationFolderPath, pathname);
var assetPath = Path.Combine(item, "asset");
if (File.Exists(assetPath))
{
var folder = Path.GetDirectoryName(Path.GetFullPath(path));
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
if (overwrite || !File.Exists(path)) File.Copy(assetPath, path, true);
}
else
{
var folder = path;
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
}
var assetMetaPath = Path.Combine(item, "asset.meta");
var metaPath = path + ".meta";
if (File.Exists(assetMetaPath))
{
if (overwrite || !File.Exists(metaPath)) File.Copy(assetMetaPath, metaPath, true);
}
}
Directory.Delete(tempFolder, true);
}
}
}
using McMaster.Extensions.CommandLineUtils;
using System.ComponentModel.DataAnnotations;
namespace ExtractUnityPackage
{
[Command(Description = "A global tool for extracting .unitypackage", Name = "dotnet ExtractUnityPackage")]
public class Program
{
[Argument(0, Description = "source .unitypackage path")]
[Required]
public string Package { get; }
[Argument(1, Description = "destination folder path")]
[Required]
public string Destination { get; }
[Option("-o|--overwrite", Description = "overwrites if file exists")]
public bool Overwrite { get; }
static void Main(string[] args)
{
CommandLineApplication.Execute<Program>(args);
}
public void OnExecute()
{
Extractor.ImportUnityPackage(Package, Destination, Overwrite);
}
}
}
原理解析
通过上面的主要代码,我们可以看到其实unitypackage就是一个简单的压缩包,解压出来的文件如下图所示,像乱码一样,文件也不明文。
随便找个目录看下,找到pathname。
打开pathname会发现这个就是文件的原始路径,以及asset就是文件的原始文件,如图所示就是一个iron.png图,将asset改名为iron.png会发现就可以访问了。
所以总的来说原理就是解析每个目录下的pathname,将asset拷贝到对应目录下,组装成一个解压出来的包内容。
请注意,该工具运行需要电脑安装有.net环境,如果有疑问,请评论或加Q群提问:Unity开发探讨交流 904994482。
工具包资源路径:https://download.csdn.net/download/egostudio/88949421
如果需要免费下载该资源包,请加群获取。
该工具基于GitHub开源dotnet-ExtractUnityPackage进行了修改,解决了里面的一点报错,如果需要源码可以访问这里。GitHub - ufcpp/dotnet-ExtractUnityPackage: A dotnet global tool for extracting .unitypackage