//##############################################################################################
    // 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);
        }
    }
Пример #4
0
    //##############################################################################################
    // 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;
                }
            }
        }
    }