1、目标
游戏中通过Save Game保存角色位置,当重启游戏后,通过Load Game可以恢复角色的位置。
2、Player对象操作
(1)组件添加
给Hierarchy下的Player组件添加Generate GUID组件。
(2)修改SceneSave.cs脚本
添加2行代码:
using System.Collections.Generic;[System.Serializable]public class SceneSave
{public Dictionary<string, bool> boolDictionary; // string key is an identifier name we choose for this listpublic Dictionary<string, string> stringDictionary; public Dictionary<string, Vector3Serializable> vector3Dictionary; // 可以保存角色位置// string key is an identifier name we choose for this listpublic List<SceneItem> listSceneItem;public Dictionary<string, GridPropertyDetails> gridPropertyDetailsDictionary; // key是坐标信息,value是地面属性信息
}
(3)修改Settings.cs脚本
添加PersistentScene的常量,因为Player是在该Scene下。
添加1行代码如下:
(4)修改Player.cs脚本
添加以下代码:
using System;
using UnityEngine.SceneManagement;
修改Player类继承自ISaveable:
接下来就是实现ISaveable定义的属性。
private string _iSaveableUniqueID;public string ISaveableUniqueID { get { return _iSaveableUniqueID; } set { _iSaveableUniqueID = value; } }private GameObjectSave _gameObjectSave;public GameObjectSave GameObjectSave { get { return _gameObjectSave; } set { _gameObjectSave = value; } }
在Awake方法中添加属性的初始化:
在OnDisable和OnEnable中各添加一个步骤:
添加这7个方法的实现:
public void ISaveableRegister()
{SaveLoadManager.Instance.iSaveableObjectList.Add(this);
}public void ISaveableDeregister()
{SaveLoadManager.Instance.iSaveableObjectList.Remove(this);
}public GameObjectSave ISaveableSave()
{// Delete saveScene for game object if it already existsGameObjectSave.sceneData.Remove(Settings.PersistentScene);// Create saveSave for game objectSceneSave sceneSave = new SceneSave();// Create Vector3 DictionarysceneSave.vector3Dictionary = new Dictionary<string, Vector3Serializable>();// Create String DictionarysceneSave.stringDictionary = new Dictionary<string, string>(); // Add Player position to Vector3 dictionaryVector3Serializable vector3Serializable = new Vector3Serializable(transform.position.x, transform.position.y, transform.position.z);sceneSave.vector3Dictionary.Add("playerPosition", vector3Serializable);// Add Current Scene Name to string dictionarysceneSave.stringDictionary.Add("currentScene", SceneManager.GetActiveScene().name);// Add Player Direction to string dictionarysceneSave.stringDictionary.Add("playerDirection", playerDirection.ToString());// Add sceneSave data for player game objectGameObjectSave.sceneData.Add(Settings.PersistentScene, sceneSave);return GameObjectSave;
}public void ISaveableLoad(GameSave gameSave)
{if(gameSave.gameObjectData.TryGetValue(ISaveableUniqueID, out GameObjectSave gameObjectSave)){// Get save data dictionary for sceneif(gameObjectSave.sceneData.TryGetValue(Settings.PersistentScene, out SceneSave sceneSave)){// Get player positionif(sceneSave.vector3Dictionary != null && sceneSave.vector3Dictionary.TryGetValue("playerPosition", out Vector3Serializable playerPosition)){transform.position = new Vector3(playerPosition.x, playerPosition.y, playerPosition.z);}// Get string dictionaryif(sceneSave.stringDictionary != null){// Get player sceneif(sceneSave.stringDictionary.TryGetValue("currentScene", out string currentScene)){SceneControllerManager.Instance.FadeAndLoadScene(currentScene, transform.position);}// Get player directionif(sceneSave.stringDictionary.TryGetValue("playerDirection", out string playerDir)){bool playerDirFound = Enum.TryParse<Direction>(playerDir, true, out Direction direction);if (playerDirFound){playerDirection = direction;SetPlayerDirection(playerDirection);}}}}}
}public void ISaveableStoreScene(string sceneName)
{// Nothing required here since the player is on a persistent scene;
}public void ISaveableRestoreScene(string sceneName)
{// Nothing required here since the player is on a persistent scene;
}private void SetPlayerDirection(Direction playerDirection)
{switch(playerDirection){case Direction.up:// set idle up triggerEventHandler.CallMovementEvent(0f, 0f, false, false, false, false, ToolEffect.none, false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false, true, false, false, false);break;case Direction.down:// set idle down triggerEventHandler.CallMovementEvent(0f, 0f, false, false, false, false, ToolEffect.none, false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false, false, true, false, false);break;case Direction.left:EventHandler.CallMovementEvent(0f, 0f, false, false, false, false, ToolEffect.none, false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false, false, false, true, false);break;case Direction.right:EventHandler.CallMovementEvent(0f, 0f, false, false, false, false, ToolEffect.none, false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false, false, false, false, true);break;default:// set idle down triggerEventHandler.CallMovementEvent(0f, 0f, false, false, false, false, ToolEffect.none, false, false, false, false, false, false, false, false,false, false, false, false, false, false, false, false, false, true, false, false);break;}
}
3、运行游戏
角色种植了Crop,然后进入另一个Scene后,选择Save Game。
重启游戏后,选择 Load Game,此时:
1)角色在另一个Scene中,并且direction保持一直
2)之前种植的Crop状态未变化