Unity敌人位置存档加载问题:数组为空报错求解决方案
解决Unity敌人位置存档/读档的数组为空问题
核心问题梳理
你遇到的报错有两个关键原因:
enemiesPositions数组未提前初始化长度,直接赋值索引会触发空引用异常- Unity的
JsonUtility无法序列化GameObject类型,你存的enemies数组在JSON里会是空的,读档时根本拿不到有效引用
修复步骤
1. 修改存档数据类(SavedData)
移除无法序列化的GameObject[],只保留用于存储位置的Vector3[]:
public class SavedData { public Vector3[] enemiesPositions; }
2. 修正存档逻辑(SaveData方法)
先获取所有敌人,初始化位置数组长度,再循环赋值每个敌人的位置:
public void SaveData() { GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy"); SavedData savedData = new SavedData(); // 初始化位置数组长度与敌人数量一致 savedData.enemiesPositions = new Vector3[enemies.Length]; // 遍历赋值每个敌人的位置 for (int i = 0; i < enemies.Length; i++) { savedData.enemiesPositions[i] = enemies[i].transform.position; } string jsonData = JsonUtility.ToJson(savedData); string filePath = Application.persistentDataPath + "/SavedData.json"; Debug.Log("存档路径:" + filePath); System.IO.File.WriteAllText(filePath, jsonData); }
3. 修正读档逻辑(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[] enemies = GameObject.FindGameObjectsWithTag("Enemy"); // 校验敌人数量与存档位置数量是否匹配 if (enemies.Length != savedData.enemiesPositions.Length) { Debug.LogWarning("当前敌人数量与存档时不一致,可能无法正确恢复位置"); } // 遍历给每个敌人设置存档位置 for (int i = 0; i < Mathf.Min(enemies.Length, savedData.enemiesPositions.Length); i++) { enemies[i].transform.position = savedData.enemiesPositions[i]; } }
完整脚本代码
using UnityEngine; public class SaveSystem : MonoBehaviour { void Update() { if (Input.GetKeyDown(KeyCode.F5)) { SaveData(); } if (Input.GetKeyDown(KeyCode.F9)) { LoadData(); } } public void SaveData() { GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy"); SavedData savedData = new SavedData(); savedData.enemiesPositions = new Vector3[enemies.Length]; for (int i = 0; i < enemies.Length; i++) { savedData.enemiesPositions[i] = enemies[i].transform.position; } string jsonData = JsonUtility.ToJson(savedData); string filePath = Application.persistentDataPath + "/SavedData.json"; Debug.Log("存档路径:" + filePath); System.IO.File.WriteAllText(filePath, jsonData); } 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[] enemies = GameObject.FindGameObjectsWithTag("Enemy"); if (enemies.Length != savedData.enemiesPositions.Length) { Debug.LogWarning("当前敌人数量与存档时不一致,可能无法正确恢复位置"); } for (int i = 0; i < Mathf.Min(enemies.Length, savedData.enemiesPositions.Length); i++) { enemies[i].transform.position = savedData.enemiesPositions[i]; } } } public class SavedData { public Vector3[] enemiesPositions; }
额外说明
GameObject.FindGameObjectsWithTag会返回场景中所有带对应标签的对象,读档时依赖这个来找到敌人,确保敌人的标签始终是"Enemy"- 加入了存档文件存在性检查和数量匹配警告,避免运行时异常
- 如果你需要区分不同敌人(比如敌人有唯一ID),可以扩展SavedData存储ID和位置的对应关系,避免因敌人顺序变化导致位置赋值错误
内容的提问来源于stack exchange,提问作者Gryffox
相关产品推荐
相关产品推荐

