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

Unity脚本保存敌人位置后无法加载,如何修复?

问题核心原因

你无法通过JsonUtility序列化GameObject类型的对象,Unity的场景对象引用无法被JSON直接保存和恢复。你的SavedData类中enemies数组在保存时根本没被写入JSON文件,加载后这个数组是空的,所以你写的循环自然没有效果。

解决方案

基础版(敌人数量/顺序固定场景)

这种方案适用于敌人数量固定、加载时场景中敌人顺序和保存时一致的情况:

  1. 修改SavedData类,只保存位置数据:
public class SavedData
{
    public Vector3[] enemiesPositions;
}
  1. 简化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);
}
  1. 修复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];
    }
}

进阶版(支持动态敌人场景)

如果敌人会动态生成/销毁,或者顺序可能变化,需要给每个敌人添加唯一标识来匹配位置:

  1. 创建敌人ID组件:
public class EnemyID : MonoBehaviour
{
    public string uniqueID; // 可在Inspector手动设置,或启动时生成随机唯一值
}
  1. 修改SavedData和对应的位置数据类:
[System.Serializable]
public class EnemyPositionData
{
    public string enemyID;
    public Vector3 position;
}

public class SavedData
{
    public EnemyPositionData[] enemyPositionDatas;
}
  1. 更新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);
}
  1. 更新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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 11:35:22