如何在运行时保存和更新“.xml”文件?
How to save and update ".xml" file at runtime?
我正在开发一个游戏项目,我们将玩家收集的物品保存到 .xml 文件中,我们这样做是为了跟踪玩家的开发过程。例如,您要进入地牢杀死敌人。在你杀死敌人后,游戏会掉落随机物品,如果你想将该物品添加到你的库存中,你只需点击它即可。这就是问题发生的地方。将新项目保存到 xml 文档的功能工作正常,但如果我手动刷新 xml 页面或重新启动游戏,它只会添加收集的项目。 (在这种情况下我们不想要)有什么方法或解决方法可以让我更新 xml 文档并在游戏 运行 时保存它?
我试图通过使用 "XmlTextWriter" class 来解决这个问题,但它最终从数据库中删除了所有项目并开始重新插入所有项目。
这让我想到了性能。
这是将新项目保存到数据库的函数。
"ContentDataCarrier" 是 class,其中包含有关项目的信息。 (ID, Name, Effects, SellPrice 等)
public void AddItemToDatabase(ContentDataCarrier contentDataCarrier)
{
var databaseDocument = new XmlDocument();
// Load the database XML document with the file path.
// Note: We need to make sure if "AssetDatabase.GetAssetPath()" function also works at runtime.
databaseDocument.Load(AssetDatabase.GetAssetPath(_itemProgressDatabase));
// Now create new nodes for each property that "contentDataCarrier" has.
XmlNode itemWrapperNode = databaseDocument.CreateElement("item");
XmlNode idNode = databaseDocument.CreateElement("ID");
idNode.InnerText = LastAddedItemID++.ToString();
XmlNode levelNode = databaseDocument.CreateElement("level");
levelNode.InnerText = contentDataCarrier.Level.ToString();
XmlNode nameNode = databaseDocument.CreateElement("name");
nameNode.InnerText = contentDataCarrier.Name;
XmlNode descriptionNode = databaseDocument.CreateElement("description");
descriptionNode.InnerText = contentDataCarrier.Description;
XmlNode spriteNode = databaseDocument.CreateElement("sprite");
spriteNode.InnerText = "null"; // Somehow find a way to save sprite id and load it into game.
XmlNode qualityNode = databaseDocument.CreateElement("quality");
qualityNode.InnerText = contentDataCarrier.Quality.ToString();
XmlNode slotTypeNode = databaseDocument.CreateElement("slotType");
slotTypeNode.InnerText = contentDataCarrier.SlotType.ToString();
XmlNode sellPriceNode = databaseDocument.CreateElement("sellPrice");
sellPriceNode.InnerText = contentDataCarrier.SellPrice.ToString();
XmlNode buyPriceNode = databaseDocument.CreateElement("buyPrice");
buyPriceNode.InnerText = contentDataCarrier.BuyPrice.ToString();
XmlNode sellableNode = databaseDocument.CreateElement("sellable");
sellableNode.InnerText = contentDataCarrier.Sellable.ToString();
XmlNode droppedFromEnemyNode = databaseDocument.CreateElement("droppedFromEnemy");
droppedFromEnemyNode.InnerText = contentDataCarrier.DroppedFromEnemy.ToString();
XmlNode itemEffectsListNode = databaseDocument.CreateElement("effects");
AddItemEffectsToDatabase(databaseDocument, itemEffectsListNode, contentDataCarrier.ItemEffects);
// Save the new item.
itemWrapperNode.AppendChild(idNode);
itemWrapperNode.AppendChild(levelNode);
itemWrapperNode.AppendChild(nameNode);
itemWrapperNode.AppendChild(descriptionNode);
itemWrapperNode.AppendChild(spriteNode);
itemWrapperNode.AppendChild(qualityNode);
itemWrapperNode.AppendChild(slotTypeNode);
itemWrapperNode.AppendChild(sellPriceNode);
itemWrapperNode.AppendChild(buyPriceNode);
itemWrapperNode.AppendChild(sellableNode);
itemWrapperNode.AppendChild(droppedFromEnemyNode);
itemWrapperNode.AppendChild(itemEffectsListNode);
databaseDocument.DocumentElement.InsertAfter(itemWrapperNode,
databaseDocument.DocumentElement.LastChild);
databaseDocument.Save(AssetDatabase.GetAssetPath(_itemProgressDatabase));
}
我希望在运行时将玩家收集的物品保存到 xml 文件。
我终于找到了让它工作的方法。我只是像@derHugo 建议的那样使用了 XMLSerializer。
使用 XMLSerializer,我可以随时从“.xml”文件中保存和获取数据。
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using UnityEngine;
[DisallowMultipleComponent]
internal sealed class XMLManager : MonoBehaviour
{
public ItemDatabase ItemDatabase = new ItemDatabase();
public void SaveItem()
{
var xmlSerializer = new XmlSerializer(typeof(ItemDatabase));
var fileStream = new FileStream(Application.dataPath + "/StreamingFiles/XML/Items.xml", FileMode.Create);
xmlSerializer.Serialize(fileStream, ItemDatabase);
fileStream.Close();
}
public void LoadItem()
{
var xmlSerializer = new XmlSerializer(typeof(ItemDatabase));
var fileStream = new FileStream(Application.dataPath + "/StreamingFiles/XML/Items.xml", FileMode.Open);
ItemDatabase = xmlSerializer.Deserialize(fileStream) as ItemDatabase;
fileStream.Close();
}
}
[System.Serializable]
public sealed class Item
{
public string Name;
public string Description;
public int Damage;
public Source Element;
public enum Source { Fire, Water, Air };
}
[System.Serializable]
public sealed class ItemDatabase
{
public List<Item> items = new List<Item>();
}
这是适合我的代码。
希望这对外面的人有所帮助。
谢谢。
我正在开发一个游戏项目,我们将玩家收集的物品保存到 .xml 文件中,我们这样做是为了跟踪玩家的开发过程。例如,您要进入地牢杀死敌人。在你杀死敌人后,游戏会掉落随机物品,如果你想将该物品添加到你的库存中,你只需点击它即可。这就是问题发生的地方。将新项目保存到 xml 文档的功能工作正常,但如果我手动刷新 xml 页面或重新启动游戏,它只会添加收集的项目。 (在这种情况下我们不想要)有什么方法或解决方法可以让我更新 xml 文档并在游戏 运行 时保存它?
我试图通过使用 "XmlTextWriter" class 来解决这个问题,但它最终从数据库中删除了所有项目并开始重新插入所有项目。 这让我想到了性能。
这是将新项目保存到数据库的函数。 "ContentDataCarrier" 是 class,其中包含有关项目的信息。 (ID, Name, Effects, SellPrice 等)
public void AddItemToDatabase(ContentDataCarrier contentDataCarrier)
{
var databaseDocument = new XmlDocument();
// Load the database XML document with the file path.
// Note: We need to make sure if "AssetDatabase.GetAssetPath()" function also works at runtime.
databaseDocument.Load(AssetDatabase.GetAssetPath(_itemProgressDatabase));
// Now create new nodes for each property that "contentDataCarrier" has.
XmlNode itemWrapperNode = databaseDocument.CreateElement("item");
XmlNode idNode = databaseDocument.CreateElement("ID");
idNode.InnerText = LastAddedItemID++.ToString();
XmlNode levelNode = databaseDocument.CreateElement("level");
levelNode.InnerText = contentDataCarrier.Level.ToString();
XmlNode nameNode = databaseDocument.CreateElement("name");
nameNode.InnerText = contentDataCarrier.Name;
XmlNode descriptionNode = databaseDocument.CreateElement("description");
descriptionNode.InnerText = contentDataCarrier.Description;
XmlNode spriteNode = databaseDocument.CreateElement("sprite");
spriteNode.InnerText = "null"; // Somehow find a way to save sprite id and load it into game.
XmlNode qualityNode = databaseDocument.CreateElement("quality");
qualityNode.InnerText = contentDataCarrier.Quality.ToString();
XmlNode slotTypeNode = databaseDocument.CreateElement("slotType");
slotTypeNode.InnerText = contentDataCarrier.SlotType.ToString();
XmlNode sellPriceNode = databaseDocument.CreateElement("sellPrice");
sellPriceNode.InnerText = contentDataCarrier.SellPrice.ToString();
XmlNode buyPriceNode = databaseDocument.CreateElement("buyPrice");
buyPriceNode.InnerText = contentDataCarrier.BuyPrice.ToString();
XmlNode sellableNode = databaseDocument.CreateElement("sellable");
sellableNode.InnerText = contentDataCarrier.Sellable.ToString();
XmlNode droppedFromEnemyNode = databaseDocument.CreateElement("droppedFromEnemy");
droppedFromEnemyNode.InnerText = contentDataCarrier.DroppedFromEnemy.ToString();
XmlNode itemEffectsListNode = databaseDocument.CreateElement("effects");
AddItemEffectsToDatabase(databaseDocument, itemEffectsListNode, contentDataCarrier.ItemEffects);
// Save the new item.
itemWrapperNode.AppendChild(idNode);
itemWrapperNode.AppendChild(levelNode);
itemWrapperNode.AppendChild(nameNode);
itemWrapperNode.AppendChild(descriptionNode);
itemWrapperNode.AppendChild(spriteNode);
itemWrapperNode.AppendChild(qualityNode);
itemWrapperNode.AppendChild(slotTypeNode);
itemWrapperNode.AppendChild(sellPriceNode);
itemWrapperNode.AppendChild(buyPriceNode);
itemWrapperNode.AppendChild(sellableNode);
itemWrapperNode.AppendChild(droppedFromEnemyNode);
itemWrapperNode.AppendChild(itemEffectsListNode);
databaseDocument.DocumentElement.InsertAfter(itemWrapperNode,
databaseDocument.DocumentElement.LastChild);
databaseDocument.Save(AssetDatabase.GetAssetPath(_itemProgressDatabase));
}
我希望在运行时将玩家收集的物品保存到 xml 文件。
我终于找到了让它工作的方法。我只是像@derHugo 建议的那样使用了 XMLSerializer。 使用 XMLSerializer,我可以随时从“.xml”文件中保存和获取数据。
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using UnityEngine;
[DisallowMultipleComponent]
internal sealed class XMLManager : MonoBehaviour
{
public ItemDatabase ItemDatabase = new ItemDatabase();
public void SaveItem()
{
var xmlSerializer = new XmlSerializer(typeof(ItemDatabase));
var fileStream = new FileStream(Application.dataPath + "/StreamingFiles/XML/Items.xml", FileMode.Create);
xmlSerializer.Serialize(fileStream, ItemDatabase);
fileStream.Close();
}
public void LoadItem()
{
var xmlSerializer = new XmlSerializer(typeof(ItemDatabase));
var fileStream = new FileStream(Application.dataPath + "/StreamingFiles/XML/Items.xml", FileMode.Open);
ItemDatabase = xmlSerializer.Deserialize(fileStream) as ItemDatabase;
fileStream.Close();
}
}
[System.Serializable]
public sealed class Item
{
public string Name;
public string Description;
public int Damage;
public Source Element;
public enum Source { Fire, Water, Air };
}
[System.Serializable]
public sealed class ItemDatabase
{
public List<Item> items = new List<Item>();
}
这是适合我的代码。
希望这对外面的人有所帮助。
谢谢。