//############################################################################################## // After loading a valid save, apply it, while keeping in mind what mode we're in. // // The modes are important for keeping it clear what level of restoration we want. For example, // if we're loading from the main menu, we want a Full load, restoring the players position // and respawn point. // However, loading a level triggers a applySave, but on in PerLevel mode, so that the save runs // for the objects that just got loaded, only applying operations that are for level objects. // For example, open doors in that level that saved that they had been opened. //############################################################################################## public void ApplySave(SaveApplicationMode mode) { Logger.Info("=== Applying Save " + mode + " ==="); // Apply operations that happen regardless of mode go here if (mode == SaveApplicationMode.Full) { // Apply operations that happen only when fully loading the game state here GameObject loadedRespawn = ToSceneGameObject(save.currentRespawn); if (loadedRespawn != null) { PlayerRespawnVolumeComponent.SetCurrentRespawn(loadedRespawn); } // Finishing our example, get the player's position back out of the savedata, and // apply it. Only do this for a full load, so we don't teleport the player around every // time a level loads. GameObject player = ToSceneGameObject(save.playerGameObject); if (player != null) { player.transform.position = ToVector3(save.playerPosition); } } else if (mode == SaveApplicationMode.PerLevel) { // Apply operations that happen only after a level is loaded go here } }
//############################################################################################## // External setter for manually setting the game's respawn, either from default, from trigger, // or from things like restoring a saved game. //############################################################################################## public static void SetCurrentRespawn(GameObject respawnObject) { PlayerRespawnVolumeComponent respawnVolume = respawnObject.GetComponent <PlayerRespawnVolumeComponent>(); if (respawnVolume) { Logger.Info("Player respawn set: " + respawnObject.name + ", position: " + respawnVolume.respawnPosition.position); currentRespawn = respawnVolume; } else { Logger.Info("Invalid actor passed into SetCurrentRespawn: " + respawnObject); } }
//############################################################################################## // Before writing to disk, update the save's information with all the information about the // world. //############################################################################################## public void UpdateSave() { // Continuing the example save data, get the player's position and fill out the save data GameObject player = FirstPersonPlayerComponent.player.gameObject; save.playerGameObject = FromSceneGameObject(player); save.playerPosition = FromVector3(player.transform.position); PlayerRespawnVolumeComponent respawnComponent = PlayerRespawnVolumeComponent.GetCurrentRespawn(); if (respawnComponent) { save.currentRespawn = FromSceneGameObject(respawnComponent.gameObject); } }
//############################################################################################## // Either fade out if dead, or teleport then fade in if respawning. //############################################################################################## void UpdateRespawn() { if (respawnState == RespawnState.Dying || respawnState == RespawnState.Respawning) { float t = respawnTimer.Parameterized(); if (fade != null) { if (respawnState == RespawnState.Dying) { fade.color = new Color(0.0f, 0.0f, 0.0f, t); } else { fade.color = new Color(0.0f, 0.0f, 0.0f, 1.0f - t); } } if (respawnTimer.Finished()) { if (respawnState == RespawnState.Dying) { respawnTimer.Start(); respawnState = RespawnState.Respawning; velocity = Vector3.zero; // Uncomment this to save on player respawn // SaveLoadManagerComponent.Instance().Save(); PlayerRespawnVolumeComponent currentRespawn = PlayerRespawnVolumeComponent.GetCurrentRespawn(); if (currentRespawn) { transform.position = currentRespawn.respawnPosition.transform.position; playerCamera.transform.localRotation = currentRespawn.transform.rotation; playerInputLookRotation = currentRespawn.transform.rotation; } else { // In case there's no respawn point, teleport the player up a bunch. transform.position = new Vector3(0.0f, transform.position.y + PLAYER_RESPAWN_HEIGHT_OFFSET, 0.0f); playerCamera.transform.localRotation = Quaternion.identity; playerInputLookRotation = Quaternion.identity; } transform.rotation = Quaternion.identity; // This is not ideal, but since CharacterController requires being grounded to set // velocity - something that can't be guaranteed on death - We have to destroy and // recreate the component to trigger a re-initialize, which zeroes out the velocity. Vector3 c_center = character.center; float c_height = character.height; float c_minMoveDistance = character.minMoveDistance; float c_radius = character.radius; float c_skinWidth = character.skinWidth; float c_slopeLimit = character.slopeLimit; float c_stepOffset = character.stepOffset; // Unity doesn't allow two of this component at once DestroyImmediate(character); character = gameObject.AddComponent <CharacterController>(); character.center = c_center; character.height = c_height; character.minMoveDistance = c_minMoveDistance; character.radius = c_radius; character.skinWidth = c_skinWidth; character.slopeLimit = c_slopeLimit; character.stepOffset = c_stepOffset; character.enabled = true; movementEnabled = true; lookingEnabled = true; damage.Respawn(); } else { respawnState = RespawnState.Alive; } } } }