Unity脚本保存敌人位置后无法加载,如何修复?
问题核心原因
你无法通过JsonUtility序列化GameObject类型的对象,Unity的场景对象引用无法被JSON直接保存和恢复。你的SavedData类中enemies数组在保存时根本没被写入JSON文件,加载后这个数组是空的,所以你写的循环自然没有效果。
解决方案
基础版(敌人数量/顺序固定场景)
这种方案适用于敌人数量固定、加载时场景中敌人顺序和保存时一致的情况:
- 修改
SavedData类,只保存位置数据:
public class SavedData { public Vector3[] enemiesPositions; }
- 简化
SaveData方法,去掉无用的GameObject数组保存:
public void SaveData() { GameObject[] gameObjects = GameObject.FindGameObjectsWithTag("Enemy"); SavedData savedData = new SavedData { enemiesPositions = gameObjects.Select(enemy => enemy.transform.position).ToArray() }; string jsonData = JsonUtility.ToJson(savedData); string filePath = Application.persistentDataPath + "/SavedData.json"; Debug.Log(filePath); System.IO.File.WriteAllText(filePath, jsonData); }
- 修复
LoadData方法,重新获取场景中的敌人并设置位置:
public void LoadData() { string filePath = Application.persistentDataPath + "/SavedData.json"; if (!System.IO.File.Exists(filePath)) { Debug.LogError("存档文件不存在"); return; } string jsonData = System.IO.File.ReadAllText(filePath); SavedData savedData = JsonUtility.FromJson<SavedData>(jsonData); GameObject[] currentEnemies = GameObject.FindGameObjectsWithTag("Enemy"); if (currentEnemies.Length != savedData.enemiesPositions.Length) { Debug.LogWarning("当前敌人数量与存档不匹配,无法完全加载位置"); return; } for (int i = 0; i < currentEnemies.Length; i++) { currentEnemies[i].transform.position = savedData.enemiesPositions[i]; } }
进阶版(支持动态敌人场景)
如果敌人会动态生成/销毁,或者顺序可能变化,需要给每个敌人添加唯一标识来匹配位置:
- 创建敌人ID组件:
public class EnemyID : MonoBehaviour { public string uniqueID; // 可在Inspector手动设置,或启动时生成随机唯一值 }
- 修改
SavedData和对应的位置数据类:
[System.Serializable] public class EnemyPositionData { public string enemyID; public Vector3 position; } public class SavedData { public EnemyPositionData[] enemyPositionDatas; }
- 更新
SaveData方法,保存ID和位置的对应关系:
public void SaveData() { GameObject[] gameObjects = GameObject.FindGameObjectsWithTag("Enemy"); List<EnemyPositionData> positionDatas = new List<EnemyPositionData>(); foreach (var enemy in gameObjects) { EnemyID enemyID = enemy.GetComponent<EnemyID>(); if (enemyID == null || string.IsNullOrEmpty(enemyID.uniqueID)) { Debug.LogError($"敌人{enemy.name}缺少有效ID,无法保存"); continue; } positionDatas.Add(new EnemyPositionData { enemyID = enemyID.uniqueID, position = enemy.transform.position }); } SavedData savedData = new SavedData { enemyPositionDatas = positionDatas.ToArray() }; string jsonData = JsonUtility.ToJson(savedData); string filePath = Application.persistentDataPath + "/SavedData.json"; Debug.Log(filePath); System.IO.File.WriteAllText(filePath, jsonData); }
- 更新
LoadData方法,通过ID匹配敌人并设置位置:
public void LoadData() { string filePath = Application.persistentDataPath + "/SavedData.json"; if (!System.IO.File.Exists(filePath)) { Debug.LogError("存档文件不存在"); return; } string jsonData = System.IO.File.ReadAllText(filePath); SavedData savedData = JsonUtility.FromJson<SavedData>(jsonData); GameObject[] currentEnemies = GameObject.FindGameObjectsWithTag("Enemy"); foreach (var data in savedData.enemyPositionDatas) { GameObject targetEnemy = currentEnemies.FirstOrDefault(e => e.GetComponent<EnemyID>()?.uniqueID == data.enemyID); if (targetEnemy != null) { targetEnemy.transform.position = data.position; } else { Debug.LogWarning($"找不到ID为{data.enemyID}的敌人,跳过位置设置"); } } }
内容的提问来源于stack exchange,提问作者Gryffox
相关产品推荐
相关产品推荐

