解决方法为Texture2D.GetData方法

我使用Monogame将XNA游戏转换为iOS游戏。
在下面的代码片段中, smallDeform是一个我称之为GetData方法的Texture2D

 smallDeform = Game.Content.Load<Texture2D>("Terrain/..."); smallDeform.GetData(smallDeformData, 0, smallDeform.Width * smallDeform.Height); 

我有一些Monogame的问题,因为iOS中的function还没有实现,因为它返回这个exception。

 #if IOS throw new NotImplementedException(); #elif ANDROID 

我尝试从Windows的XML文件中序列化数据以从iOS加载整个文件。 序列化的文件每个重量超过100MB,这是不可接受的parsing。

基本上,我正在寻找一种解决方法,从纹理中获取数据(例如uint[]Color[] ),而不使用GetData方法。

PS:我在Mac上,所以我不能使用Monogame SharpDX库。

提前致谢。

序列化数据实际上是一个非常聪明的解决方法,但是XML对于这项工作来说太重了。 我会做的是使用自定义,但简单的二进制格式,以便您可以控制输出的大小。

这里有几个方法我鞭打应该工作,但请注意,我专门做了他们回答这个问题,他们还没有经过testing。

保存数据

  private void SaveTextureData(Texture2D texture, string filename) { int width = texture.Width; int height = texture.Height; Color[] data = new Color[width * height]; texture.GetData<Color>(data, 0, data.Length); using (BinaryWriter writer = new BinaryWriter(File.Open(filename, FileMode.Create))) { writer.Write(width); writer.Write(height); writer.Write(data.Length); for (int i = 0; i < data.Length; i++) { writer.Write(data[i].R); writer.Write(data[i].G); writer.Write(data[i].B); writer.Write(data[i].A); } } } 

并加载数据..

  private Texture2D LoadTextureData(string filename) { using (BinaryReader reader = new BinaryReader(File.Open(filename, FileMode.Open))) { var width = reader.ReadInt32(); var height = reader.ReadInt32(); var length = reader.ReadInt32(); var data = new Color[length]; for (int i = 0; i < data.Length; i++) { var r = reader.ReadByte(); var g = reader.ReadByte(); var b = reader.ReadByte(); var a = reader.ReadByte(); data[i] = new Color(r, g, b, a); } var texture = new Texture2D(GraphicsDevice, width, height); texture.SetData<Color>(data, 0, data.Length); return texture; } } 

二进制数据比XML数据小得多。 这是关于你将得到没有压缩一样小。 请注意,二进制格式在更改时非常严格。 如果你需要改变格式,在大多数情况下写出新文件会更容易。

如果您需要更改方法,请小心保持同步。 每个写入应该以完全相同的顺序和数据types与相同的读取相匹配。

我有兴趣知道文件变小了多less。 让我知道事情的后续?

我回答自己的问题,如果有人会有同样的问题。

根据craftworkgame的build议,我使用字节stream保存了我的数据,但由于没有File类,我不得不使用WinRT函数:

 private async void SaveColorArray(string filename, Color[] array) { StorageFile sampleFile = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(filename + ".dat", CreationCollisionOption.ReplaceExisting); IRandomAccessStream writeStream = await sampleFile.OpenAsync(FileAccessMode.ReadWrite); IOutputStream outputSteam = writeStream.GetOutputStreamAt(0); DataWriter dataWriter = new DataWriter(outputSteam); for (int i = 0; i < array.Length; i++) { dataWriter.WriteByte(array[i].R); dataWriter.WriteByte(array[i].G); dataWriter.WriteByte(array[i].B); dataWriter.WriteByte(array[i].A); } await dataWriter.StoreAsync(); await outputSteam.FlushAsync(); } protected async Task<Color[]> LoadColorArray(string filename) { StorageFile sampleFile = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(filename + ".dat", CreationCollisionOption.OpenIfExists); IRandomAccessStream readStream = await sampleFile.OpenAsync(FileAccessMode.Read); IInputStream inputSteam = readStream.GetInputStreamAt(0); DataReader dataReader = new DataReader(inputSteam); await dataReader.LoadAsync((uint)readStream.Size); Color[] levelArray = new Color[dataReader.UnconsumedBufferLength / 4]; int i = 0; while (dataReader.UnconsumedBufferLength > 0) { byte[] colorArray = new byte[4]; dataReader.ReadBytes(colorArray); levelArray[i++] = new Color(colorArray[0], colorArray[1], colorArray[2], colorArray[3]); } return levelArray; } 

如果你愿意构build你自己的MonoGame版本,你可以在iOS上使用Texture2D.GetData。 看到修复这里: https : //github.com/scottlerch/MonoGame/commit/24c1c3d5398f4ed9dbd9b60c0bbdbc096311632c )。

这是从这个同样的问题在这里讨论: https : //monogame.codeplex.com/discussions/442667

该修复程序已被确认在iPad1 v5.1.1 +和iPhone4 v6.1 +上运行。