You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity敌人位置存档加载问题:数组为空报错求解决方案

解决Unity敌人位置存档/读档的数组为空问题

核心问题梳理

你遇到的报错有两个关键原因:

  1. enemiesPositions数组未提前初始化长度,直接赋值索引会触发空引用异常
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 22:09:59