EASY PAK的源代码(在Code Plex上)
如果要载入很大数量的文件的时候,使用Easy Pak打包成.pak文件可以通过减少查找时间而显著加快读取速度。
但是我发现这个Easy Pak现在有几个bug
在PakContentManager下,有几个去扩展名的方法不对
string[] GetAssetNames()
/// <summary> /// Gets an array of the asset names of the content inside the pak file. /// </summary> /// <returns>An array of strings with all the asset names.</returns> public string[] GetAssetNames() { if (pakFile == null) throw new NullReferenceException("Attempting to call GetAssetNames() when pak file is released or not yet loaded"); List<string> filenames = new List<string>(); foreach (PakEntry entry in pakFile) { string name = entry.FileName; if (name.EndsWith(".xnb")) name = name.Remove(name.Length - 4, 4); // 原来的源代码里是name.Length - 4, 3,其实应该是name.Length - 4, 4,不然名字的最后多一个b filenames.Add(name); } return filenames.ToArray(); }
以及 string[] GetAssetNamesFromDirectory(string)
/// <summary> /// Gets an array of asset names from a specific directory within /// the pak file. /// </summary> /// <param name="directory">The directory to get asset names from</param> /// <returns>An array of strings with all the asset names</returns> public string[] GetAssetNamesFromDirectory(string directory) { if (pakFile == null) throw new NullReferenceException(string.Format("Attempting to call GetAssetNamesFromDirectory(\"{0}\") when pak file is released or not yet loaded", directory)); List<string> filenames = new List<string>(); foreach (PakEntry entry in pakFile) { string name = entry.FileName; if (name.EndsWith(".xnb")) name = name.Remove(name.Length - 4, 4); // 这个也是 string[] parts = name.Split(‘\\‘); string dir = ""; for (int i = 0; i < parts.Length - 1; i++) dir += parts[i] + "/"; if (dir == directory) filenames.Add(name); } return filenames.ToArray(); }
修改完毕之后就可以build了
然后在你的XNA项目的.csproj文件中加入
注意AssemblyFile改成你编译的那几个dll的位置。
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. --> <Target Name="BeforeBuild"> </Target> <UsingTask TaskName="EasyPak.PakWriter" AssemblyFile="c:\EasyPak\EasyPakWriter.dll" /> <Target Name="AfterBuild"> <PropertyGroup> <OutDir>bin\$(Platform)\$(Configuration)\Content\</OutDir> <ContentDir>bin\$(Platform)\$(Configuration)\Content\</ContentDir> <PakName>content.pak</PakName> <IncludeFolders></IncludeFolders> <ExcludeFolders></ExcludeFolders> <ExcludeExtensions>.xgs;.xwb;.xsb;.pak</ExcludeExtensions> </PropertyGroup> <EasyPak.PakWriter OutDir="$(OutDir)" ContentDir="$(ContentDir)" PakName="$(PakName)" IncludeFolders="$(IncludeFolders)" ExcludeFolders="$(ExcludeFolders)" ExcludeExtensions="$(ExcludeExtensions)" /> </Target>
然后你编译你的XNA游戏之后,Easy Pak会在build结束之后打包你的游戏资源。
Easy Pak会检查已经存在的pak,如果不需要重新打包的话他是不会重新打的。
注意VS不知道.pak文件在Content目录下。所以不会自己清理。但是实际上不需要清理,除非你决定不用easy pak了。。。
要在游戏里使用Easy Pak加载文件怎么做呢?在游戏的LoadContent方法中
/// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); // TODO: use this.Content to load your game content here Content = new PakContentManager(this.Services, "Content/content.pak"); font = Content.Load<SpriteFont>("SpriteFont1"); font2 = Content.Load<SpriteFont>(@"Fonts\SpriteFont2"); // 这里加载其他资源... // 最后释放pak文件 (Content as PakContentManager).ReleasePakFile(); }
另外最后,Easy Pak打包了你的资源,却留下一大堆空目录。
修改PakWriter 让它自动删除空目录吧
bool Execute()方法最后加入调用一个递归删空目录的方法(从stackoverflow直接拿过来的。。)
注意在return true之前调用 ProcessDirectory(fullContentPath)
private static void ProcessDirectory(string startLocation) { foreach (var directory in Directory.GetDirectories(startLocation)) { ProcessDirectory(directory); if (Directory.GetFiles(directory).Length == 0 && Directory.GetDirectories(directory).Length == 0) { Directory.Delete(directory, false); } } }
最后总结几点
1. Easy Pak适合打包大数量的文件
2. Easy Pak只打包,不压缩。而且默认.xgs / .xwb / .xsb / .pak 这几个扩展名的文件是不打包的(XACT的音效资源本身就被打包过了)
3. 如果需要压缩文件,在XNA项目里设置属性 “Content Build”里面有一个 Compress content pipeline output files 打勾就可以。压缩的是XNA资源文件,Easy Pak依旧不压缩
4. 如果资源不是很大,可以在游戏一开始就把整个pak载入了。
原文:http://www.cnblogs.com/thefake/p/3541190.html