读取 Unity HoloLens 项目中的 XML 个文件:在编辑器中工作,而不是在部署的项目中工作
Reading XML files in a Unity HoloLens project : works in Editor, not in deployed project
我正在尝试保存和加载自定义 class 'Animation'(四元数列表,一个 int 表示 ID,一个 int 表示有多少个游戏对象要设置动画) ,并且保存部分在 HoloLens 上工作得很好,但加载部分由于某些原因只能在 PC 上工作。在 HoloLens 上,它 returns 错误:"There is an error in XML document (2, 2)."
我已经尝试使用 StreamingAssets 而不是 'persistentDataPath' 来处理我的文件,但是在 HoloLens 上,我再次收到一条错误,说明对文件的访问被拒绝。
我也试过使用 TextReader 和 StreamReader 加载 'Animation',但结果完全一样。
我也试过使用 StreamWriter 编写 'Animation',但结果也没有改变。
我已经加入了 class 的代码,负责编写和加载 XML 文件,以及 'SaveAnimation' 函数写入的示例每次都成功。
知道问题出在哪里吗?我很确定问题出在我如何编写 XML 文件,但我似乎找不到解决方案。
代码为Save/Load class:
using System.IO;
using System.Xml.Serialization;
using UnityEngine;
public class AnimationSaverLoader : MonoBehaviour {
private string baseFilename = "animation";
private string path;
public bool SaveAnimation(Animation animation)
{
int animationID = animation.AnimationID;
path = Path.GetFullPath(Path.Combine(Application.persistentDataPath, baseFilename + animationID + ".xml"));
try
{
using (FileStream writer = new FileStream(path, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(Animation));
serializer.Serialize(writer, animation);
}
return true;
}
catch (System.Exception e)
{
Debug.LogWarning("Error saving animation : " + e.Message);
return false;
}
}
public Animation LoadAnimation(int animationID)
{
path = Path.GetFullPath(Path.Combine(Application.persistentDataPath, baseFilename + animationID + ".xml"));
Animation deserialized = null;
try
{
using (FileStream reader = File.Open(path, FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(Animation));
deserialized = (Animation)serializer.Deserialize(reader);
}
}
catch (System.Exception e)
{
Debug.LogWarningFormat("Error loading animation : {0}", e.Message);
}
Debug.LogFormat("deserialized is null : {0}", deserialized == null);
return deserialized;
}
以及 'SaveAnimation' 函数的 XML 输出示例:
<?xml version="1.0" encoding="utf-8"?>
<Animation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<nbAnimatables>7</nbAnimatables>
<animationID>1</animationID>
<points>
<ArrayOfQuaternion>
<Quaternion>
<x>0</x>
<y>0</y>
<z>0</z>
<w>1</w>
<eulerAngles>
<x>-0</x>
<y>0</y>
<z>0</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>0</x>
<y>0</y>
<z>0</z>
<w>1</w>
<eulerAngles>
<x>-0</x>
<y>0</y>
<z>0</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0</x>
<y>-0</y>
<z>-0</z>
<w>1</w>
<eulerAngles>
<x>-0</x>
<y>0</y>
<z>0</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0.229409814</x>
<y>0.0272422452</y>
<z>-0.114730783</z>
<w>0.966160357</w>
<eulerAngles>
<x>334.0847</x>
<y>6.722004</y>
<z>344.9074</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0.0120867919</x>
<y>0.009940858</y>
<z>-0.0253626034</z>
<w>0.9995558</w>
<eulerAngles>
<x>358.644348</x>
<y>1.17417169</y>
<z>357.0791</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>0.2436451</x>
<y>-0.03456776</y>
<z>0.0332907774</z>
<w>0.9686763</w>
<eulerAngles>
<x>28.3156128</x>
<y>356.695343</y>
<z>3.10282016</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0.0274707</x>
<y>-0.004143617</y>
<z>0.0005820858</z>
<w>0.9996139</w>
<eulerAngles>
<x>356.852</x>
<y>359.5228</y>
<z>0.0798406</z>
</eulerAngles>
</Quaternion>
</ArrayOfQuaternion>
<ArrayOfQuaternion>
<Quaternion>
<x>-0</x>
<y>-0</y>
<z>0.5602086</z>
<w>0.8283516</w>
<eulerAngles>
<x>-0</x>
<y>-0</y>
<z>68.14045</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>0</x>
<y>0</y>
<z>0</z>
<w>1</w>
<eulerAngles>
<x>-0</x>
<y>0</y>
<z>0</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0</x>
<y>-0</y>
<z>-0</z>
<w>1</w>
<eulerAngles>
<x>-0</x>
<y>0</y>
<z>0</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0.229409814</x>
<y>0.0272422452</y>
<z>-0.114730783</z>
<w>0.966160357</w>
<eulerAngles>
<x>334.0847</x>
<y>6.722004</y>
<z>344.9074</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0.0120867919</x>
<y>0.009940858</y>
<z>-0.0253626034</z>
<w>0.9995558</w>
<eulerAngles>
<x>358.644348</x>
<y>1.17417169</y>
<z>357.0791</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>0.243645117</x>
<y>-0.0345677622</y>
<z>0.03329078</z>
<w>0.9686764</w>
<eulerAngles>
<x>28.3156128</x>
<y>356.695343</y>
<z>3.10282016</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0.0274707</x>
<y>-0.004143617</y>
<z>0.0005820858</z>
<w>0.9996139</w>
<eulerAngles>
<x>356.852</x>
<y>359.5228</y>
<z>0.0798406</z>
</eulerAngles>
</Quaternion>
</ArrayOfQuaternion>
</points>
</Animation>
编辑:认为 'Animation' class 也很有用。
using UnityEngine;
using System.Collections.Generic;
using System.Xml.Serialization;
[XmlRoot("Animation")]
public class Animation {
[XmlElement("nbAnimatables")]
public int NbAnimatables { get; set; }
[XmlElement("animationID")]
public int AnimationID { get; set; }
[XmlArray("points")]
public List<Quaternion[]> Points { get; private set; }
public Animation()
{
}
public Animation(int nbAnimatables, int animationID)
{
this.NbAnimatables = nbAnimatables;
this.AnimationID = animationID;
Points = new List<Quaternion[]>();
}
public bool AddPoint(Quaternion[] animatableRotations)
{
if (animatableRotations.Length == NbAnimatables)
{
Points.Add(animatableRotations);
return true;
}
return false;
}
public bool OverridePoint(Quaternion[] animatableRotations, int pointIndex)
{
if (pointIndex < Points.Count)
{
Points[pointIndex] = animatableRotations;
return true;
}
return false;
}
public bool RemovePoint(int pointIndex)
{
if (pointIndex < Points.Count)
{
Points.RemoveAt(pointIndex);
return true;
}
return false;
}
}
尝试以下操作:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(path, settings);
XmlSerializer serializer = new XmlSerializer(typeof(Animation));
serializer.Serialize(writer, animation);
我会尝试使用 StorageFile API :
Windows.Storage.StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
string fileName = baseFilename + animationID + ".xml");
Windows.Storage.StorageFile sampleFile = await storageFolder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.ReplaceExisting);
using (var stream = await sampleFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);)
{
using (var outputStream = stream.GetOutputStreamAt(0))
{
XmlSerializer serializer = new XmlSerializer(typeof(Animation));
serializer.Serialize(stream, animation);
await outputStream.FlushAsync();
}
}
的更多信息
听从 jdweng 的建议,我决定改变我写文件的方式。我再次尝试了 StreamWriter,由于某种原因,它成功了!我通过这个更改了第 18 行的代码:
using (StreamWriter writer = new StreamWriter(File.Create(path)))
{
XmlSerializer serializer = new XmlSerializer(typeof(Animation));
serializer.Serialize(writer, animation);
}
我正在尝试保存和加载自定义 class 'Animation'(四元数列表,一个 int 表示 ID,一个 int 表示有多少个游戏对象要设置动画) ,并且保存部分在 HoloLens 上工作得很好,但加载部分由于某些原因只能在 PC 上工作。在 HoloLens 上,它 returns 错误:"There is an error in XML document (2, 2)."
我已经尝试使用 StreamingAssets 而不是 'persistentDataPath' 来处理我的文件,但是在 HoloLens 上,我再次收到一条错误,说明对文件的访问被拒绝。
我也试过使用 TextReader 和 StreamReader 加载 'Animation',但结果完全一样。
我也试过使用 StreamWriter 编写 'Animation',但结果也没有改变。
我已经加入了 class 的代码,负责编写和加载 XML 文件,以及 'SaveAnimation' 函数写入的示例每次都成功。
知道问题出在哪里吗?我很确定问题出在我如何编写 XML 文件,但我似乎找不到解决方案。
代码为Save/Load class:
using System.IO;
using System.Xml.Serialization;
using UnityEngine;
public class AnimationSaverLoader : MonoBehaviour {
private string baseFilename = "animation";
private string path;
public bool SaveAnimation(Animation animation)
{
int animationID = animation.AnimationID;
path = Path.GetFullPath(Path.Combine(Application.persistentDataPath, baseFilename + animationID + ".xml"));
try
{
using (FileStream writer = new FileStream(path, FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(Animation));
serializer.Serialize(writer, animation);
}
return true;
}
catch (System.Exception e)
{
Debug.LogWarning("Error saving animation : " + e.Message);
return false;
}
}
public Animation LoadAnimation(int animationID)
{
path = Path.GetFullPath(Path.Combine(Application.persistentDataPath, baseFilename + animationID + ".xml"));
Animation deserialized = null;
try
{
using (FileStream reader = File.Open(path, FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(Animation));
deserialized = (Animation)serializer.Deserialize(reader);
}
}
catch (System.Exception e)
{
Debug.LogWarningFormat("Error loading animation : {0}", e.Message);
}
Debug.LogFormat("deserialized is null : {0}", deserialized == null);
return deserialized;
}
以及 'SaveAnimation' 函数的 XML 输出示例:
<?xml version="1.0" encoding="utf-8"?>
<Animation xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<nbAnimatables>7</nbAnimatables>
<animationID>1</animationID>
<points>
<ArrayOfQuaternion>
<Quaternion>
<x>0</x>
<y>0</y>
<z>0</z>
<w>1</w>
<eulerAngles>
<x>-0</x>
<y>0</y>
<z>0</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>0</x>
<y>0</y>
<z>0</z>
<w>1</w>
<eulerAngles>
<x>-0</x>
<y>0</y>
<z>0</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0</x>
<y>-0</y>
<z>-0</z>
<w>1</w>
<eulerAngles>
<x>-0</x>
<y>0</y>
<z>0</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0.229409814</x>
<y>0.0272422452</y>
<z>-0.114730783</z>
<w>0.966160357</w>
<eulerAngles>
<x>334.0847</x>
<y>6.722004</y>
<z>344.9074</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0.0120867919</x>
<y>0.009940858</y>
<z>-0.0253626034</z>
<w>0.9995558</w>
<eulerAngles>
<x>358.644348</x>
<y>1.17417169</y>
<z>357.0791</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>0.2436451</x>
<y>-0.03456776</y>
<z>0.0332907774</z>
<w>0.9686763</w>
<eulerAngles>
<x>28.3156128</x>
<y>356.695343</y>
<z>3.10282016</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0.0274707</x>
<y>-0.004143617</y>
<z>0.0005820858</z>
<w>0.9996139</w>
<eulerAngles>
<x>356.852</x>
<y>359.5228</y>
<z>0.0798406</z>
</eulerAngles>
</Quaternion>
</ArrayOfQuaternion>
<ArrayOfQuaternion>
<Quaternion>
<x>-0</x>
<y>-0</y>
<z>0.5602086</z>
<w>0.8283516</w>
<eulerAngles>
<x>-0</x>
<y>-0</y>
<z>68.14045</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>0</x>
<y>0</y>
<z>0</z>
<w>1</w>
<eulerAngles>
<x>-0</x>
<y>0</y>
<z>0</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0</x>
<y>-0</y>
<z>-0</z>
<w>1</w>
<eulerAngles>
<x>-0</x>
<y>0</y>
<z>0</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0.229409814</x>
<y>0.0272422452</y>
<z>-0.114730783</z>
<w>0.966160357</w>
<eulerAngles>
<x>334.0847</x>
<y>6.722004</y>
<z>344.9074</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0.0120867919</x>
<y>0.009940858</y>
<z>-0.0253626034</z>
<w>0.9995558</w>
<eulerAngles>
<x>358.644348</x>
<y>1.17417169</y>
<z>357.0791</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>0.243645117</x>
<y>-0.0345677622</y>
<z>0.03329078</z>
<w>0.9686764</w>
<eulerAngles>
<x>28.3156128</x>
<y>356.695343</y>
<z>3.10282016</z>
</eulerAngles>
</Quaternion>
<Quaternion>
<x>-0.0274707</x>
<y>-0.004143617</y>
<z>0.0005820858</z>
<w>0.9996139</w>
<eulerAngles>
<x>356.852</x>
<y>359.5228</y>
<z>0.0798406</z>
</eulerAngles>
</Quaternion>
</ArrayOfQuaternion>
</points>
</Animation>
编辑:认为 'Animation' class 也很有用。
using UnityEngine;
using System.Collections.Generic;
using System.Xml.Serialization;
[XmlRoot("Animation")]
public class Animation {
[XmlElement("nbAnimatables")]
public int NbAnimatables { get; set; }
[XmlElement("animationID")]
public int AnimationID { get; set; }
[XmlArray("points")]
public List<Quaternion[]> Points { get; private set; }
public Animation()
{
}
public Animation(int nbAnimatables, int animationID)
{
this.NbAnimatables = nbAnimatables;
this.AnimationID = animationID;
Points = new List<Quaternion[]>();
}
public bool AddPoint(Quaternion[] animatableRotations)
{
if (animatableRotations.Length == NbAnimatables)
{
Points.Add(animatableRotations);
return true;
}
return false;
}
public bool OverridePoint(Quaternion[] animatableRotations, int pointIndex)
{
if (pointIndex < Points.Count)
{
Points[pointIndex] = animatableRotations;
return true;
}
return false;
}
public bool RemovePoint(int pointIndex)
{
if (pointIndex < Points.Count)
{
Points.RemoveAt(pointIndex);
return true;
}
return false;
}
}
尝试以下操作:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(path, settings);
XmlSerializer serializer = new XmlSerializer(typeof(Animation));
serializer.Serialize(writer, animation);
我会尝试使用 StorageFile API :
Windows.Storage.StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
string fileName = baseFilename + animationID + ".xml");
Windows.Storage.StorageFile sampleFile = await storageFolder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.ReplaceExisting);
using (var stream = await sampleFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);)
{
using (var outputStream = stream.GetOutputStreamAt(0))
{
XmlSerializer serializer = new XmlSerializer(typeof(Animation));
serializer.Serialize(stream, animation);
await outputStream.FlushAsync();
}
}
的更多信息
听从 jdweng 的建议,我决定改变我写文件的方式。我再次尝试了 StreamWriter,由于某种原因,它成功了!我通过这个更改了第 18 行的代码:
using (StreamWriter writer = new StreamWriter(File.Create(path)))
{
XmlSerializer serializer = new XmlSerializer(typeof(Animation));
serializer.Serialize(writer, animation);
}