1、目標
將游戲保存到文件,并從文件中加載游戲。
Player在游戲中種植的Crop,我們希望保存到文件中,當游戲重新加載時Crop的GridProperty數據仍然存在。這次主要實現保存地面屬性(GridProperties)信息。
我們要做的是實現一個我們可以點擊的方式,將游戲保存到一個文件中,然后點擊加載按鈕,它將獲取該文件,然后將數據帶回游戲中。
2、創建GameSave.cs腳本
在Assets/Scripts/SaveSystem下創建新的腳本命名為:GameSave.cs。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[System.Serializable]
public class GameSave
{// string key - GUID gameobject IDpublic Dictionary<string, GameObjectSave> gameObjectData;public GameSave(){gameObjectData = new Dictionary<string, GameObjectSave>();}
}
3、修改ISaveable.cs腳本
添加2行代碼:
GameObjectSave ISaveableSave();void ISaveableLoad(GameSave gameSave);
ISaveableSave: 保存變量和游戲對象,這一步是獲取數據,后續會寫入文件
ISaveableLoad:將游戲保存數據對象(從文件中讀取的數據)作為它的參數
4、修改GridPropertiesManager.cs腳本
添加新的引用:
using UnityEngine.SceneManagement;
添加ISaveableLoad函數實現:
public void ISaveableLoad(GameSave gameSave)
{if(gameSave.gameObjectData.TryGetValue(ISaveableUniqueID, out GameObjectSave gameObjectSave)){GameObjectSave = gameObjectSave;// Restore data for current sceneISaveableRestoreScene(SceneManager.GetActiveScene().name);}
}
其中,ISaveableUniqueID是通過GetComponent<GenerateGUID>().GUID生成的。
在GenerateGUID的實現中,它的屬性是[ExecuteAlways],即運行/編譯時都會執行,實際上是需要編譯時生成_gUID信息。_gUID是[SerializeField]屬性,而[SerializeField]
?標記的字段會被 Unity 自動序列化到場景文件或預制體中。
所以一個游戲中,GenerateGUID的值是不會變化的。
另外,GameObjectSave是屬性變量,其定義為:
? ? public GameObjectSave GameObjectSave { get { return _gameObjectSave; } set { _gameObjectSave = value; } }
?
添加ISaveableSave方法的實現:
public GameObjectSave ISaveableSave(){// Store current scene dataISaveableStoreScene(SceneManager.GetActiveScene().name);return GameObjectSave;}
5、修改SceneItemsManager.cs腳本?
?添加新的引用:
using UnityEngine.SceneManagement;
添加如下2個方法的實現:
public void ISaveableLoad(GameSave gameSave){if(gameSave.gameObjectData.TryGetValue(ISaveableUniqueID, out GameObjectSave gameObjectSave)){GameObjectSave = gameObjectSave;// Restore data for current sceneISaveableRestoreScene(SceneManager.GetActiveScene().name);}}public GameObjectSave ISaveableSave(){// Store current scene dataISaveableStoreScene(SceneManager.GetActiveScene().name);return GameObjectSave;}
6、修改SaveLoadManager.cs腳本
SaveLoadManager有2個方法:StoreCurrentSceneData /?RestoreCurrentSceneData。
在SceneControllerManager中,當場景切換和Start中會使用RestoreCurrentSceneData方法。
接下來就是改造SaveLoadManager,從文件中讀寫信息。
添加2個引用:
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
接著添加2個函數:
public void LoadDataFromFile()
{BinaryFormatter bf = new BinaryFormatter();if(File.Exists(Application.persistentDataPath + "/WildHopeCreek.data")){gameSave = new GameSave();FileStream file = File.Open(Application.persistentDataPath + "/WildHopeCreek.data", FileMode.Open);gameSave = (GameSave)bf.Deserialize(file); // loop through all ISaveable obvjects and apply save datafor(int i = iSaveableObjectList.Count - 1; i > -1; i--){if (gameSave.gameObjectData.ContainsKey(iSaveableObjectList[i].ISaveableUniqueID)){iSaveableObjectList[i].ISaveableLoad(gameSave);}else{// else if iSaveableObject unique ID is not in the game object data then destroy objectComponent component = (Component)iSaveableObjectList[i];Destroy(component.gameObject);}}file.Close();}UIManager.Instance.DisablePauseMenu();
}public void SaveDataToFile()
{gameSave = new GameSave();// loop through all ISaveable objects and generate save dataforeach(ISaveable iSaveableObject in iSaveableObjectList){gameSave.gameObjectData.Add(iSaveableObject.ISaveableUniqueID, iSaveableObject.ISaveableSave());}BinaryFormatter bf = new BinaryFormatter();FileStream file = File.Open(Application.persistentDataPath + "/WildHopeCreek.data" , FileMode.Create);bf.Serialize(file, gameSave);file.Close();UIManager.Instance.DisablePauseMenu();
}
可以通過如下代碼查看存儲的路徑:
Debug.Log("dataPath:" + Application.persistentDataPath);
我的地址是:C:\Users\benbe\AppData\LocalLow\DefaultCompany\XingluValley
7、編輯UI界面
(1)設置界面元素
將PauseMenuPanel下的Tab2修改為Tab2SaveGame,
將SelectionTabButtonsPanel -> SelectionButton(2) -> Text的輸入改為"Save/Load"。
給Tab2SaveGame對象添加Vertical Layout Group組件,相關配置如下:
在Tab2SaveGame下右擊 -> UI -> Button(TextMeshPro),命名為SavevGameButton。再創建一個同樣的Button命名為LoadGameButton。
分別點擊SaveGameButton及LoadGameButton兩個對象,修改Button屬性的Normal Color為87775D? ,Highlighed Color為D8DB84? ?。
最后界面呈現的樣式為:
(2)添加點擊事件
SaveGameButton對應的點擊事件:
LoadGameButton對應的點擊事件:
8、運行游戲
運行游戲,收集地面上的item,并且種植了Crop,點擊Esc -> Save Game。
退出游戲后重新進入,點擊Esc -> Load Game。之前地面上已經被收集掉的item沒有再次出現,Crop仍然保持之前的狀態。