コード例 #1
0
        /// <summary>
        /// Saves all relevant game data per the scene and specified fullSave value.
        /// </summary>
        /// <param name="fullSave">If true, 'last manually saved scene' and player location data are also saved. If false, these are skipped and just the other scene object data is saved.</param>
        /// <returns>True if operation was a success. False if there was an error. In the case of an error, an exception likely occured, and an exception message will be printed.</returns>
        private IEnumerator saveDataForCurrentScene(bool fullSave)
        {
            float           operationStartTime = Time.time;
            bool            result             = true;
            BinaryFormatter formatter          = new BinaryFormatter();
            FileStream      fsCore             = null;
            FileStream      fsPlayer           = null;
            FileStream      fsInventory        = null;
            FileStream      fsLevel            = null;

            FPESceneSaveData       sceneData          = mySaveLoadLogic.gatherSceneData();
            FPEInventorySaveData   inventoryData      = mySaveLoadLogic.gatherInventorySaveData();
            FPEPlayerStateSaveData playerLocationData = mySaveLoadLogic.gatherPlayerData();

            FPEInventoryWorldSaveData[]        worldInventoryData   = mySaveLoadLogic.gatherInventoryInWorld();
            FPEPickupWorldSaveData[]           worldPickupData      = mySaveLoadLogic.gatherPickupsInWorld();
            FPETriggerSaveData[]               triggerSaveData      = mySaveLoadLogic.gatherTriggerData();
            FPEActivateSaveData[]              activateSaveData     = mySaveLoadLogic.gatherActivateTypeData();
            FPEAttachedNoteSaveData[]          attachedNoteSaveData = mySaveLoadLogic.gatherAttachedNoteTypeData();
            FPEAudioDiaryPlayedStateSaveData[] playedDiarySaveData  = mySaveLoadLogic.gatherAudioDiaryPlayedStateData();
            FPEJournalSaveData[]               journalSaveData      = mySaveLoadLogic.gatherJournalSaveData();
            FPEDoorSaveData[]          doorSaveData    = mySaveLoadLogic.gatherDoorTypeData();
            FPEGenericObjectSaveData[] genericSaveData = mySaveLoadLogic.gatherGenericSaveTypeData();

            //
            // Your additional Custom Save/Load logic for custom save data types goes here
            //

            // Try to write the gathered data to applicable save files on disk
            try
            {
                // We only want to save player location data on manual save operation. When "auto-saving" on change of scene via Doorway, we just want to save the non-player level data.
                if (fullSave)
                {
                    // We also only want to write to core save file on a manual save operation. Auto-saves on level change do not count as a "full save"
                    fsCore = new FileStream(fullCoreSaveFileFullPath, FileMode.Create);
                    formatter.Serialize(fsCore, sceneData);

                    fsPlayer = new FileStream(fullPlayerLocationDataSaveFileFullPath, FileMode.Create);
                    formatter.Serialize(fsPlayer, playerLocationData);

                    fsInventory = new FileStream(fullInventoryDataSaveFileFullPath, FileMode.Create);
                    formatter.Serialize(fsInventory, inventoryData);
                }

                fsLevel = new FileStream(autoSavePath + "/" + levelDataFilePrefix + sceneData.LastSavedSceneIndex + levelDataFilePostfix, FileMode.Create);

                formatter.Serialize(fsLevel, worldInventoryData);
                formatter.Serialize(fsLevel, worldPickupData);
                formatter.Serialize(fsLevel, triggerSaveData);
                formatter.Serialize(fsLevel, activateSaveData);
                formatter.Serialize(fsLevel, attachedNoteSaveData);
                formatter.Serialize(fsLevel, playedDiarySaveData);
                formatter.Serialize(fsLevel, journalSaveData);
                formatter.Serialize(fsLevel, doorSaveData);
                formatter.Serialize(fsLevel, genericSaveData);

                // If performing a full save, we also want to flush all previous FULL save data from full directory, and replace it will the stuff we just saved to auto
                if (fullSave)
                {
                    copyAllLevelDataFromPathToPath(autoSavePath, fullSavePath);
                }
            }
            catch (Exception e)
            {
                Debug.LogError("FPESaveLoadManager:: Failed to save game file(s). Did you make a call the SaveGame() before ever calling StartANewGame()? Reason: " + e.Message);
                result = false;
            }
            finally
            {
                if (fsCore != null)
                {
                    fsCore.Close();
                }

                if (fsLevel != null)
                {
                    fsLevel.Close();
                }

                if (fsPlayer != null)
                {
                    fsPlayer.Close();
                }

                if (fsInventory != null)
                {
                    fsInventory.Close();
                }
            }

            // Last thing is to clear the progress flag to indicate we're done
            savingInProgress = false;

            yield return(result);
        }
コード例 #2
0
        /// <summary>
        /// Gathers data from player's inventory (items, audio diaries, notes)
        /// </summary>
        /// <returns>A saveable data package for the inventory at save time</returns>
        public FPEInventorySaveData gatherInventorySaveData()
        {
            #region HELD_OBJECT

            FPEInteractableBaseScript.eInteractionType heldObjectType = FPEInteractionManagerScript.Instance.getHeldObjectType();
            GameObject heldObject = FPEInteractionManagerScript.Instance.getHeldObject();

            FPEHeldObjectSaveData heldObjectData = null;

            if (heldObjectType == FPEInteractableBaseScript.eInteractionType.PICKUP)
            {
                string scrubbedName = heldObject.gameObject.name.Split(FPEObjectTypeLookup.PickupPrefabDelimiter)[0];
                // Here, we pass in the first eInventoryItems value since we'll be ignoring it anyway, and it's "better" than exposing a "NO TYPE" in the enum list in the Inspector.
                heldObjectData = new FPEHeldObjectSaveData(true, scrubbedName, FPEInventoryManagerScript.eInventoryItems.APPLE, heldObject.transform.localRotation);
            }
            else if (heldObjectType == FPEInteractableBaseScript.eInteractionType.INVENTORY)
            {
                heldObjectData = new FPEHeldObjectSaveData(true, "", heldObject.GetComponent <FPEInteractableInventoryItemScript>().InventoryItemType, heldObject.transform.localRotation);
            }
            else
            {
                heldObjectData = new FPEHeldObjectSaveData(false, "", FPEInventoryManagerScript.eInventoryItems.APPLE, Quaternion.identity);
            }

            #endregion

            FPEInventoryManagerScript invManager = FPEInventoryManagerScript.Instance;

            #region INVENTORY_ITEMS

            List <FPEInteractableInventoryItemScript> invItems = invManager.getInventoryItems();
            int[] invQty = invManager.getInventoryQuantities();
            List <FPEInventoryItemSaveData> invData = new List <FPEInventoryItemSaveData>();
            int tempQty = 0;

            for (int i = 0; i < invItems.Count; i++)
            {
                if (invItems[i].Stackable)
                {
                    tempQty = invQty[(int)invItems[i].InventoryItemType];

                    for (int q = 0; q < tempQty; q++)
                    {
                        invData.Add(new FPEInventoryItemSaveData(invItems[i].InventoryItemType));
                    }
                }
                else
                {
                    invData.Add(new FPEInventoryItemSaveData(invItems[i].InventoryItemType));
                }
            }

            #endregion

            #region NOTES_AND_AUDIO_DIARIES

            // Notes
            FPENoteEntry[]    notes    = invManager.getNoteDataForSavedGame();
            FPENoteSaveData[] noteData = new FPENoteSaveData[notes.Length];

            for (int n = 0; n < notes.Length; n++)
            {
                noteData[n] = new FPENoteSaveData(notes[n].NoteTitle, notes[n].NoteBody);
            }

            // Audio Diaries
            FPEAudioDiaryEntry[]         diaries   = invManager.getAudioDiaryDataForSavedGame();
            FPEAudioDiaryEntrySaveData[] diaryData = new FPEAudioDiaryEntrySaveData[diaries.Length];

            for (int a = 0; a < diaries.Length; a++)
            {
                diaryData[a] = new FPEAudioDiaryEntrySaveData(diaries[a].DiaryTitle, diaries[a].getAudioDiaryClipPath(), diaries[a].ShowDiaryTitle);
            }

            #endregion

            FPEInventorySaveData inventoryData = new FPEInventorySaveData(heldObjectData, invData.ToArray(), diaryData, noteData);

            return(inventoryData);
        }
コード例 #3
0
        /// <summary>
        /// Restores saved level data to the currently loaded scene, if it exists.
        /// </summary>
        /// <param name="fullLoad">If true, player location and inventory data will be loaded, and player will be relocated in world space per that data.</param>
        /// <returns>True if operation was a success. False if there was an error. In the case of an error, an exception likely occured, and an exception message will be printed.</returns>
        private IEnumerator restoreDataForCurrentScene(bool fullLoad)
        {
            bool result = true;

            // If doing a full load, we want to copy all 'full' save level data files into the 'auto' directory, then restore from there.
            if (fullLoad)
            {
                copyAllLevelDataFromPathToPath(fullSavePath, autoSavePath);
            }

            string levelDataFilename = autoSavePath + "/" + levelDataFilePrefix + SceneManager.GetActiveScene().buildIndex + levelDataFilePostfix;

            if (File.Exists(levelDataFilename))
            {
                FPEPlayerStateSaveData             loadedPlayerLocationData   = null;
                FPEInventorySaveData               loadedInventoryData        = null;
                FPEInventoryWorldSaveData[]        loadedWorldInventoryData   = null;
                FPEPickupWorldSaveData[]           loadedWorldPickupData      = null;
                FPETriggerSaveData[]               loadedTriggerData          = null;
                FPEActivateSaveData[]              loadedActivateData         = null;
                FPEAttachedNoteSaveData[]          loadedAttachedNoteData     = null;
                FPEAudioDiaryPlayedStateSaveData[] loadedAudioDiaryPlayedData = null;
                FPEJournalSaveData[]               loadedJournalData          = null;
                FPEDoorSaveData[]          loadedDoorData    = null;
                FPEGenericObjectSaveData[] loadedGenericData = null;

                BinaryFormatter formatter = new BinaryFormatter();

                FileStream fsPlayer    = null;
                FileStream fsInventory = null;
                FileStream fsLevel     = null;

                // Try to actually read in the data from disk
                try
                {
                    fsLevel = new FileStream(levelDataFilename, FileMode.Open);

                    // Note: Read the data in from file in the same order it was written to file
                    loadedWorldInventoryData   = (FPEInventoryWorldSaveData[])formatter.Deserialize(fsLevel);
                    loadedWorldPickupData      = (FPEPickupWorldSaveData[])formatter.Deserialize(fsLevel);
                    loadedTriggerData          = (FPETriggerSaveData[])formatter.Deserialize(fsLevel);
                    loadedActivateData         = (FPEActivateSaveData[])formatter.Deserialize(fsLevel);
                    loadedAttachedNoteData     = (FPEAttachedNoteSaveData[])formatter.Deserialize(fsLevel);
                    loadedAudioDiaryPlayedData = (FPEAudioDiaryPlayedStateSaveData[])formatter.Deserialize(fsLevel);
                    loadedJournalData          = (FPEJournalSaveData[])formatter.Deserialize(fsLevel);
                    loadedDoorData             = (FPEDoorSaveData[])formatter.Deserialize(fsLevel);
                    loadedGenericData          = (FPEGenericObjectSaveData[])formatter.Deserialize(fsLevel);

                    //
                    // Your additional Custom Save/Load logic for custom save data types goes here
                    //

                    // Triggers and Activate types
                    mySaveLoadLogic.restoreTriggerData(loadedTriggerData);
                    mySaveLoadLogic.restoreActivateData(loadedActivateData);

                    // Doors
                    mySaveLoadLogic.restoreDoorData(loadedDoorData);

                    // Generic Saveable Objects
                    mySaveLoadLogic.restoreGenericSaveTypeData(loadedGenericData);

                    // Inventory type objects in the world
                    mySaveLoadLogic.removeAllInventoryInWorld(fullLoad);
                    mySaveLoadLogic.createWorldInventory(loadedWorldInventoryData);

                    // Pickup type objects in the world
                    mySaveLoadLogic.removeAllPickupsInWorld(fullLoad);
                    mySaveLoadLogic.createWorldPickups(loadedWorldPickupData);

                    // Attached Notes, Diaries, and Journals
                    // Note: We restore these last, because they can be attached to Inventory Items and Pickups or other interactables. If for example, we loaded these BEFORE restoring pickups,
                    // the associated pickups would get their attached note/diary data restored, then be deleted and replaced with a fresh copy of the prefab, thus erasing the restored note/diary
                    // state. This way, we ensure the 'final' restored prefab of a pickup/inventory item is in place and loaded before we restore its attached note or diary status.
                    mySaveLoadLogic.restoreAttachedNoteData(loadedAttachedNoteData);
                    mySaveLoadLogic.restoreAudioDiaryPlaybackStateData(loadedAudioDiaryPlayedData);
                    mySaveLoadLogic.restoreJournalData(loadedJournalData);

                    // Only restore player location and move them if required. We do this last because the functions above may destroy held object, depending on fullLoad value.
                    if (fullLoad)
                    {
                        fsPlayer = new FileStream(fullPlayerLocationDataSaveFileFullPath, FileMode.Open);
                        loadedPlayerLocationData = (FPEPlayerStateSaveData)formatter.Deserialize(fsPlayer);
                        mySaveLoadLogic.relocatePlayer(loadedPlayerLocationData);

                        fsInventory         = new FileStream(fullInventoryDataSaveFileFullPath, FileMode.Open);
                        loadedInventoryData = (FPEInventorySaveData)formatter.Deserialize(fsInventory);
                        mySaveLoadLogic.restoreInventorySaveData(loadedInventoryData);
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError("FPESaveLoadManager:: Failed to load game file. Reason: " + e.Message);
                    result = false;
                }
                finally
                {
                    if (fsLevel != null)
                    {
                        fsLevel.Close();
                    }

                    if (fsPlayer != null)
                    {
                        fsPlayer.Close();
                    }

                    if (fsInventory != null)
                    {
                        fsInventory.Close();
                    }
                }
            }

            // Last thing is to clear the progress flag to indicate we're done
            restoringDataInProgress = false;

            yield return(result);
        }
コード例 #4
0
        /// <summary>
        /// Restores player's inventory (items, audio diaries, notes)
        /// </summary>
        /// <param name="data">The data from which to base restored inventory</param>
        public void restoreInventorySaveData(FPEInventorySaveData data)
        {
            FPEInventoryManagerScript invManager = FPEInventoryManagerScript.Instance;

            // Clear existing inventory
            invManager.clearInventoryItems();

            // Held Object
            FPEHeldObjectSaveData heldObjData = data.HeldObjectData;

            #region HELD_OBJECT
            if (heldObjData.HeldSomething)
            {
                GameObject tempLoadedObject = null;

                // Pickup Type
                if (heldObjData.PickupPrefabName != "")
                {
                    Object tempObject = Resources.Load(FPEObjectTypeLookup.PickupResourcePath + heldObjData.PickupPrefabName);

                    if (tempObject != null)
                    {
                        tempLoadedObject      = Instantiate(tempObject) as GameObject;
                        tempLoadedObject.name = heldObjData.PickupPrefabName;
                        tempLoadedObject.transform.localRotation = heldObjData.LocalRotation;
                    }
                    else
                    {
                        Debug.LogError("FPESaveLoadLogic:: Loading data encountered unknown Pickup named '" + heldObjData.PickupPrefabName + "'. No prefab was found with this name. This object will NOT be loaded.  Ensure that all Pickup prefabs are located in the '" + FPEObjectTypeLookup.PickupResourcePath + "' sub folder of a Resources folder.");
                    }
                }
                // Inventory Type
                else
                {
                    if (inventoryLookupTable.ContainsKey(heldObjData.InventoryItemType))
                    {
                        string tempPath = "";

                        if (inventoryLookupTable.TryGetValue(heldObjData.InventoryItemType, out tempPath))
                        {
                            tempLoadedObject = Instantiate(Resources.Load(FPEObjectTypeLookup.InventoryResourcePath + tempPath)) as GameObject;
                            tempLoadedObject.transform.localRotation = heldObjData.LocalRotation;
                        }
                        else
                        {
                            Debug.LogError("FPESaveLoadLogic:: Loading data could not get value for InventoryItemType '" + heldObjData.InventoryItemType + "'");
                        }
                    }
                    else
                    {
                        Debug.LogError("FPESaveLoadLogic:: Loading data encountered unknown InventoryItemType '" + heldObjData.InventoryItemType + "'. This object will NOT be loaded.  Ensure that all Inventory Item prefabs are located in the '" + FPEObjectTypeLookup.InventoryResourcePath + "' sub folder of a Resources folder. Also ensure that there is an entry in the FPEObjectTypeLookup 'inventoryItemsLookup' Dictionary for type '" + heldObjData.InventoryItemType + "'");
                    }
                }

                // Lastly, put the object into player's hand
                FPEInteractablePickupScript pickup = tempLoadedObject.GetComponent <FPEInteractablePickupScript>();

                if (pickup)
                {
                    FPEInteractionManagerScript.Instance.holdObjectFromGameLoad(pickup);
                }
                else
                {
                    Debug.LogError("FPESaveLoadLogic:: Loading held object for object '" + tempLoadedObject.gameObject.name + "', but its prefab had no attached FPEInteractablePickupScript component. Object will not be loaded. Check prefab.");
                }
            }
            #endregion

            #region INVENTORY_ITEMS

            FPEInventoryItemSaveData[] loadedItemData = data.InventoryItemData;

            // Create all the items, and add each to inventory
            GameObject tempInvObject = null;
            string     tempInvPath;
            FPEInteractableInventoryItemScript tempInvItem = null;

            // We start at index 1 to skip over our padded 0th value
            for (int i = 0; i < loadedItemData.Length; i++)
            {
                if (inventoryLookupTable.ContainsKey(loadedItemData[i].InventoryItemType))
                {
                    // Added this as an if, did that break things?
                    if (inventoryLookupTable.TryGetValue(loadedItemData[i].InventoryItemType, out tempInvPath))
                    {
                        tempInvObject = Instantiate(Resources.Load(FPEObjectTypeLookup.InventoryResourcePath + tempInvPath)) as GameObject;
                        tempInvItem   = tempInvObject.GetComponent <FPEInteractableInventoryItemScript>();

                        if (tempInvItem != null)
                        {
                            FPEInteractionManagerScript.Instance.putObjectIntoInventory(tempInvItem, false);
                        }
                        else
                        {
                            Debug.LogError("FPESaveLoadLogic:: Loaded Inventory Item prefab '" + FPEObjectTypeLookup.InventoryResourcePath + tempInvPath + "' had no attached FPEInteractableInventoryItemScript component. Item will NOT be restored into player inventory");
                        }
                    }
                    else
                    {
                        Debug.LogError("FPESaveLoadLogic:: Loading data could not get value for InventoryItemType '" + loadedItemData[i].InventoryItemType + "'");
                    }
                }
                else
                {
                    Debug.LogError("FPESaveLoadLogic:: Loading data encountered unknown InventoryItemType '" + loadedItemData[i].InventoryItemType + "'. This object will NOT be restored into player inventory.  Ensure that there is an entry in the FPEObjectTypeLookup 'inventoryItemsLookup' Dictionary for type '" + loadedItemData[i].InventoryItemType + "'");
                }
            }

            #endregion

            #region NOTES_AND_AUDIO_DIARIES

            FPENoteSaveData[]   loadedNoteData = data.NoteData;
            List <FPENoteEntry> noteEntries    = new List <FPENoteEntry>();

            for (int n = 0; n < loadedNoteData.Length; n++)
            {
                noteEntries.Add(loadedNoteData[n].getNoteEntry());
            }

            invManager.setNoteDataFromSavedGame(noteEntries);

            FPEAudioDiaryEntrySaveData[] loadedDiaryData = data.AudioDiaryData;
            List <FPEAudioDiaryEntry>    diaryEntries    = new List <FPEAudioDiaryEntry>();

            for (int a = 0; a < loadedDiaryData.Length; a++)
            {
                diaryEntries.Add(loadedDiaryData[a].getAudioDiaryEntry());
            }

            invManager.setAudioDiaryDataFromSavedGame(diaryEntries);

            #endregion
        }