Game State

版本检查: 5.5

-

难度: 中级

Phase 6 teaches you how to create a system to load scenes while preserving game state using the Scene Manager, ScriptableObjects as temporary runtime data storage, delegates and lambda expressions. Download the asset package for Phase 6 here.

Game State

中级 Adventure Game tutorial

Download the asset package for Phase 6 at the Unity Asset Store here.

SceneController

Code snippet

using System;
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
public class SceneController : MonoBehaviour
{
    public event Action BeforeSceneUnload;
    public event Action AfterSceneLoad;
    public CanvasGroup faderCanvasGroup;
    public float fadeDuration = 1f;
    public string startingSceneName = "SecurityRoom";
    public string initialStartingPositionName = "DoorToMarket";
    public SaveData playerSaveData;
    
    
    private bool isFading;
    private IEnumerator Start ()
    {
        faderCanvasGroup.alpha = 1f;
        playerSaveData.Save (PlayerMovement.startingPositionKey, initialStartingPositionName);
        yield return StartCoroutine (LoadSceneAndSetActive (startingSceneName));
        StartCoroutine (Fade (0f));
    }
    public void FadeAndLoadScene (SceneReaction sceneReaction)
    {
        if (!isFading)
        {
            StartCoroutine (FadeAndSwitchScenes (sceneReaction.sceneName));
        }
    }
    private IEnumerator FadeAndSwitchScenes (string sceneName)
    {
        yield return StartCoroutine (Fade (1f));
        if (BeforeSceneUnload != null)
            BeforeSceneUnload ();
        yield return SceneManager.UnloadSceneAsync (SceneManager.GetActiveScene ().buildIndex);
        yield return StartCoroutine (LoadSceneAndSetActive (sceneName));
        if (AfterSceneLoad != null)
            AfterSceneLoad ();
        
        yield return StartCoroutine (Fade (0f));
    }
    private IEnumerator LoadSceneAndSetActive (string sceneName)
    {
        yield return SceneManager.LoadSceneAsync (sceneName, LoadSceneMode.Additive);
        Scene newlyLoadedScene = SceneManager.GetSceneAt (SceneManager.sceneCount - 1);
        SceneManager.SetActiveScene (newlyLoadedScene);
    }
    private IEnumerator Fade (float finalAlpha)
    {
        isFading = true;
        faderCanvasGroup.blocksRaycasts = true;
        float fadeSpeed = Mathf.Abs (faderCanvasGroup.alpha - finalAlpha) / fadeDuration;
        while (!Mathf.Approximately (faderCanvasGroup.alpha, finalAlpha))
        {
            faderCanvasGroup.alpha = Mathf.MoveTowards (faderCanvasGroup.alpha, finalAlpha,
                fadeSpeed * Time.deltaTime);
            yield return null;
        }
        isFading = false;
        faderCanvasGroup.blocksRaycasts = false;
    }
}

SaveData

Code snippet

using System;
using UnityEngine;
using System.Collections.Generic;
[CreateAssetMenu]
public class SaveData : ResettableScriptableObject
{
    [Serializable]
    public class KeyValuePairLists<T>
    {
        public List<string> keys = new List<string>();
        public List<T> values = new List<T>();
        public void Clear ()
        {
            keys.Clear ();
            values.Clear ();
        }
        public void TrySetValue (string key, T value)
        {
            int index = keys.FindIndex(x => x == key);
            if (index > -1)
            {
                values[index] = value;
            }
            else
            {
                keys.Add (key);
                values.Add (value);
            }
        }
        public bool TryGetValue (string key, ref T value)
        {
            int index = keys.FindIndex(x => x == key);
            if (index > -1)
            {
                value = values[index];
                return true;
            }
            return false;
        }
    }
    public KeyValuePairLists<bool> boolKeyValuePairLists = new KeyValuePairLists<bool> ();
    public KeyValuePairLists<int> intKeyValuePairLists = new KeyValuePairLists<int>();
    public KeyValuePairLists<string> stringKeyValuePairLists = new KeyValuePairLists<string>();
    public KeyValuePairLists<Vector3> vector3KeyValuePairLists = new KeyValuePairLists<Vector3>();
    public KeyValuePairLists<Quaternion> quaternionKeyValuePairLists = new KeyValuePairLists<Quaternion>();
    public override void Reset ()
    {
        boolKeyValuePairLists.Clear ();
        intKeyValuePairLists.Clear ();
        stringKeyValuePairLists.Clear ();
        vector3KeyValuePairLists.Clear ();
        quaternionKeyValuePairLists.Clear ();
    }
    private void Save<T>(KeyValuePairLists<T> lists, string key, T value)
    {
        lists.TrySetValue(key, value);
    }
    private bool Load<T>(KeyValuePairLists<T> lists, string key, ref T value)
    {
        return lists.TryGetValue(key, ref value);
    }
    public void Save (string key, bool value)
    {
        Save(boolKeyValuePairLists, key, value);
    }
    public void Save (string key, int value)
    {
        Save(intKeyValuePairLists, key, value);
    }
    public void Save (string key, string value)
    {
        Save(stringKeyValuePairLists, key, value);
    }
    public void Save (string key, Vector3 value)
    {
        Save(vector3KeyValuePairLists, key, value);
    }
    public void Save (string key, Quaternion value)
    {
        Save(quaternionKeyValuePairLists, key, value);
    }
    public bool Load (string key, ref bool value)
    {
        return Load(boolKeyValuePairLists, key, ref value);
    }
    public bool Load (string key, ref int value)
    {
        return Load (intKeyValuePairLists, key, ref value);
    }
    public bool Load (string key, ref string value)
    {
        return Load (stringKeyValuePairLists, key, ref value);
    }
    public bool Load (string key, ref Vector3 value)
    {
        return Load(vector3KeyValuePairLists, key, ref value);
    }
    public bool Load (string key, ref Quaternion value)
    {
        return Load (quaternionKeyValuePairLists, key, ref value);
    }
}