个人技术总结——Unity游戏开发中的保存与读取

222200207朱骏祥 2024-12-14 21:46:06
这个作业属于哪个课程软件工程24年秋季
这个作业要求在哪里软件工程实践总结&个人技术博客
这个作业的目标完成软件工程实践总结&个人技术总结,并完成相应博客
其他参考文献《构建之法》、CSDN

目录

  • 一、技术概述
  • 二、技术详述
  • 2.1 数据模型
  • 2.2 保存文件的路径
  • 2.3 保存功能实现
  • 2.4 读取功能实现
  • 2.5 查找物品和任务ID
  • 三、遇到的问题和解决方案
  • 3.1 问题1:数据丢失
  • 3.2 问题2:部分数据未加载
  • 四、总结

一、技术概述

在游戏开发中,保存与读取功能是不可或缺的核心部分,能够让玩家在退出游戏后继续从上次进度进行游戏。

本文旨在技术层面详细说明保存与读取功能的实现细节与设计思路。

保存功能: 将玩家当前游戏的状态(例如任务状态、玩家属性、位置等)以文件的形式持久化。

读取功能: 从保存文件中加载玩家的进度并还原游戏状态。

二、技术详述

2.1 数据模型

[System.Serializable]
public class GameData
{
    // 玩家数据
    public PlayerData playerData; 

    // 当前任务
    public List<TaskData> activeTasks;

    // 已完成任务
    public List<TaskData> completedTasks;

    // 背包和物品数据
    public List<ItemData> inventoryItems;

    // 玩家属性存储类
    [System.Serializable]
    public class PlayerData
    {
        public float knowledge;
        public float fitness;
        public float charm;
    }

    // 任务数据存储类
    [System.Serializable]
    public class TaskData
    {
        public int taskId;
        public string taskName;
        public string taskdescription;
        public bool isCompleted;
        public int requiredKnowledge;
        public int requiredFitness;
        public int requiredCharm;
    }

    // 物品数据存储类
    [System.Serializable]
    public class ItemData
    {
        public string itemName;
        public int itemID;
        public int itemHeld;
    }
}

2.2 保存文件的路径

在运行时生成保存文件的路径,确保可以跨平台使用:

saveFilePath = Application.persistentDataPath + "/savefile.json";

2.3 保存功能实现

保存功能负责将当前游戏状态序列化为 JSON 格式,并写入文件:

    public void SaveGame()
    {
        SaveData data = new SaveData();     
        foreach (var task in completedTasks)
        {
            Debug.Log("Completed Task: " + task.taskName + " | IsCompleted: " + task.isCompleted);
        }

        // 保存玩家属性
        data.charm = CharacterStats.Instance.GetCharm();
        data.knowledge = CharacterStats.Instance.GetKnowledge();
        data.fitness =CharacterStats.Instance.GetFitness();
        // 保存任务状态
        data.activeTaskIDs = new List<int>();
        foreach (TaskSO task in activeTasks)
        {
            data.activeTaskIDs.Add(task.taskID);
            Debug.Log(task.taskName + " Get");
        }

        data.completedTaskIDs = new List<int>();
        foreach (TaskSO task in completedTasks)
        {
            data.completedTaskIDs.Add(task.taskID);
            Debug.Log(task.taskName + " completed");
        }

        // 保存背包物品
        data.inventoryItems = new List<ItemData>();
        foreach (Item item in inventory.itemList)
        {
            ItemData itemData = new ItemData
            {
                itemName = item.itemName,
                itemID = item.itemID,
                itemHeld = item.itemHeld
            };
            data.inventoryItems.Add(itemData);
        }

        // 转换为JSON并写入文件
        string json = JsonUtility.ToJson(data, true);
        File.WriteAllText(saveFilePath, json);

        Debug.Log("游戏已保存");
    }

2.4 读取功能实现

读取功能负责从保存文件中反序列化数据并恢复游戏状态:

    public void LoadGame()
    {
        if (File.Exists(saveFilePath))
        {
            string json = File.ReadAllText(saveFilePath);
            SaveData data = JsonUtility.FromJson<SaveData>(json);

            // 加载玩家属性
            CharacterStats.SetCharm(data.charm);
            CharacterStats.SetKnowledge(data.knowledge);
            CharacterStats.SetFitness(data.fitness);

            // 加载任务状态
            activeTasks.Clear();
            completedTasks.Clear();

            foreach (int taskID in data.activeTaskIDs)
            {
                TaskSO task = FindTaskByID(taskID);
                if (task != null)
                {
                    activeTasks.Add(task);
                    // 根据任务类型分配到 mainTasks 或 sideTasks
                    if (task.isMainTask)
                    {
                        taskManager.mainTasks.Add(task);
                    }
                    else
                    {
                        taskManager.sideTasks.Add(task);
                    }
                    task.isCompleted = false;
                    Debug.Log("任务加载到 activeTasks: " + task.taskName);
                    
                }
                else
                {
                    Debug.LogWarning("未能加载任务ID: " + taskID);
                }
            }

            foreach (int taskID in data.completedTaskIDs)
            {
                TaskSO task = FindTaskByID(taskID);
                if (task != null)
                {
                    completedTasks.Add(task);
                    task.isCompleted = true;
                    Debug.Log("任务加载到 completedTasks: " + task.taskName);
                }
                else
                {
                    Debug.LogWarning("未能加载任务ID: " + taskID);
                }
            }
            

            // 加载背包物品
            inventory.itemList.Clear();
            foreach (ItemData itemData in data.inventoryItems)
            {
                Item item = FindItemByID(itemData.itemID);
                if (item != null)
                {
                    item.itemHeld = itemData.itemHeld;
                    inventory.itemList.Add(item);
                }
            }
            
            // 显示主线任务
            taskManager.DisplayTasks(taskManager.mainTasks);
            // 显示主线任务
            taskManager.DisplayTasks(taskManager.sideTasks);
            // 显示主线任务
            taskManager.DisplayTasks(taskManager.completedTasks);
            taskManager.RefreshTaskLists();
            
            
        }
        else
        {
            Debug.Log("未找到保存文件");
        }
    }

2.5 查找物品和任务ID

    private TaskSO FindTaskByID(int id)
    {
        TaskSO[] allTasks = Resources.FindObjectsOfTypeAll<TaskSO>();
        foreach (TaskSO task in allTasks)
        {
            if (task.taskID == id)
            {
                Debug.Log("找到任务: " + task.taskName + " (ID: " + task.taskID + ")");
                return task;
            }
        }
        Debug.LogWarning("未找到任务ID: " + id);
        return null;
    }

    private Item FindItemByID(int id)
    {
        foreach (Item item in inventory.itemList)
        {
            if (item.itemID == id)
            {
                return item;
            }
        }
        return null;
    }

三、遇到的问题和解决方案

3.1 问题1:数据丢失

原因:
文件写入失败或保存路径无效。
解决方案:
检查文件路径是否有效,确保具有写权限。

3.2 问题2:部分数据未加载

原因:
游戏状态的还原逻辑与保存数据不匹配。
解决方案:
确保保存和读取逻辑一致性,调试具体字段。

四、总结

通过上述技术设计,游戏的保存与读取功能可以高效、稳定地实现,并支持未来的功能扩展。玩家能够体验无缝的游戏进度保存与加载,提升游戏体验。

...全文
105 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

111

社区成员

发帖
与我相关
我的任务
社区描述
202401_CS_SE_FZU
软件工程 高校
社区管理员
  • FZU_SE_TeacherL
  • 言1837
  • 防震水泥
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧