Unity中如何读取多份ItemSettings数据并重建子GameObject状态?
问题解决:多ItemSettings序列化/反序列化与优化方案
一、循环读取多个序列化的ItemSettings
你当前的保存逻辑是逐个将ItemSettings序列化到文件,读取时需要循环调用Deserialize直到文件流到达末尾。修改读取代码如下:
public void LoadFile() { string destination = "D:/Unity/test.txt"; if (!File.Exists(destination)) { Debug.LogError("File not found"); return; } using (FileStream file = File.OpenRead(destination)) { BinaryFormatter bf = new BinaryFormatter(); List<ItemSettings> allSettings = new List<ItemSettings>(); try { // 循环反序列化直到文件流结束 while (file.Position < file.Length) { ItemSettings data = (ItemSettings)bf.Deserialize(file); allSettings.Add(data); } } catch (EndOfStreamException) { // 正常到达文件末尾,无需额外处理 } catch (Exception e) { Debug.LogError($"读取失败: {e.Message}"); } // 遍历所有配置重建对象 foreach(var settings in allSettings) { // 示例逻辑:实例化预制体并设置Transform状态 GameObject item = Instantiate(yourItemPrefab, cupboard.transform); item.transform.SetPositionAndRotation(settings.Position, settings.Rotation); item.transform.localScale = settings.Scale; // 其他自定义字段设置... } } }
注意:使用
using语句会自动管理文件流生命周期,比手动调用Close()更安全,能避免异常场景下的资源泄漏。
二、更优实现方案
逐个序列化存在效率低、维护复杂的问题,且Unity 2021+版本中BinaryFormatter已被标记为不安全且过时,推荐以下两种更可靠的方案:
方案1:序列化整个ItemSettings列表
将所有需要保存的ItemSettings存入一个List<ItemSettings>,一次性完成序列化/反序列化,代码更简洁且效率更高:
保存代码修改:
public void SaveProject() { string path = "D:/Unity/test.txt"; List<ItemSettings> allSettings = new List<ItemSettings>(); foreach (Transform g in cupboard.transform) { CubeObject cubeObject = g.GetComponent<CubeObject>(); if (cubeObject) { allSettings.Add(cubeObject.GetSettings()); } } using (FileStream file = File.Create(path)) { BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(file, allSettings); } }
读取代码修改:
public void LoadFile() { string destination = "D:/Unity/test.txt"; if (!File.Exists(destination)) { Debug.LogError("File not found"); return; } using (FileStream file = File.OpenRead(destination)) { try { BinaryFormatter bf = new BinaryFormatter(); List<ItemSettings> allSettings = (List<ItemSettings>)bf.Deserialize(file); foreach(var settings in allSettings) { // 重建对象逻辑 GameObject item = Instantiate(yourItemPrefab, cupboard.transform); item.transform.SetPositionAndRotation(settings.Position, settings.Rotation); item.transform.localScale = settings.Scale; } } catch (Exception e) { Debug.LogError($"读取失败: {e.Message}"); } } }
方案2:使用JsonUtility替代BinaryFormatter
Json格式可读性更强,且Unity内置的JsonUtility无安全漏洞,适合序列化简单数据结构:
确保ItemSettings可序列化:
[System.Serializable] public class ItemSettings { public Vector3 Position; public Quaternion Rotation; public Vector3 Scale; // 其他需要保存的自定义字段... }
保存代码:
public void SaveProject() { string path = "D:/Unity/test.json"; List<ItemSettings> allSettings = new List<ItemSettings>(); foreach (Transform g in cupboard.transform) { CubeObject cubeObject = g.GetComponent<CubeObject>(); if (cubeObject) { allSettings.Add(cubeObject.GetSettings()); } } // 用包装类解决JsonUtility无法直接序列化List的问题 SettingsWrapper wrapper = new SettingsWrapper(); wrapper.SettingsList = allSettings; string json = JsonUtility.ToJson(wrapper, prettyPrint: true); File.WriteAllText(path, json); } // 用于Json序列化的List包装类 [System.Serializable] public class SettingsWrapper { public List<ItemSettings> SettingsList; }
读取代码:
public void LoadFile() { string destination = "D:/Unity/test.json"; if (!File.Exists(destination)) { Debug.LogError("File not found"); return; } string json = File.ReadAllText(destination); SettingsWrapper wrapper = JsonUtility.FromJson<SettingsWrapper>(json); foreach(var settings in wrapper.SettingsList) { GameObject item = Instantiate(yourItemPrefab, cupboard.transform); item.transform.SetPositionAndRotation(settings.Position, settings.Rotation); item.transform.localScale = settings.Scale; } }
提示:若需要更小的文件体积或加密需求,可以在Json基础上添加压缩或加密逻辑。
内容的提问来源于stack exchange,提问作者Sabre
相关产品推荐
相关产品推荐

