FarmRPG　Unity Preserving Scene State  Part2 　保存したStateから復元する

# 概要
今回はStateの復元を実装します。

以下実装後の様子
![0619.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/311164c7-857c-0cfb-9b7f-2ddff1cb4871.gif)


参考　実装前の様子　シーンを再読み込みすると取ったアイテムが再生成される。これを改善したい。

![0622.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/32aa868d-c32a-dbe5-5aa4-b73e15094d55.gif)


# 開発環境

IDE:Rider
Unity:2020.3.42(LTS)
OS:Windows10

# UnityEditor上の設定
変更点なし

# 実装のポイント

## SeceneItemsManagerクラス
SeceneItemsManagerクラスに以下３点のメソッドを加えます。

DestorySceneItems：初期シーンのアイテムを全部削除する
InstantiateSceneItems：Stateに基づいてアイテムを生成する
ISaveableRestoreScene：上２つの関数を実行する。SaveLoadManagerクラスのRestoreCurrentCurrentSceneDataメソッドから実行される


## SaveLoadManagerクラス
SaveLoadManagerクラスに以下メソッドを加えます。
RestoreCurrentSceneData：iSaveableObject.RestoreSceneを実行実行するメソッドを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/c5d5d0ee-b74a-2e2d-eb8a-af2e120c3f1f.png)


# コード部分

## SceneControllerManager

```diff_c_sharp:SceneControllerManager.cs

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.SceneManagement;

public class SceneControllerManager :SingletonMonobehaviour<SceneControllerManager>
{
    private IEnumerator FadeAndSwitchScenes(string sceneName, Vector3 spawnPosition)
    {
        yield return StartCoroutine(Fade(1f));
        SaveLoadManager.Instance.StoreCurrentSceneData();    
    
        Player.Instance.gameObject.transform.position = spawnPosition;
        yield return SceneManager.UnloadSceneAsync(SceneManager.GetActiveScene().buildIndex);

        yield return StartCoroutine(LoadSceneAndSetActive(sceneName));
        
        EventHandler.CallAfterSceneLoadEvent();
        
+        SaveLoadManager.Instance.RestoreCurrentSceneData();
        
        yield return StartCoroutine(Fade(0f)); 
    }

    public void FadeAndLoadScene(string sceneName, Vector3 spawnPosition)
    {
        if (!isFading)
        {
            StartCoroutine(FadeAndSwitchScenes(sceneName, spawnPosition));
        }
    }   
}
```


## SaveLoadManager

```diff_c_sharp:SaveLoadManager.cs
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SaveLoadManager : SingletonMonobehaviour<SaveLoadManager>
{
    public List<ISaveable> iSaveableObjectList;

    protected override void Awake()
    {
        base.Awake();
        iSaveableObjectList = new List<ISaveable>();
    }
+    public void RestoreCurrentSceneData()
+    {
+        foreach(ISaveable iSaveableObject in iSaveableObjectList)
+        {
+            iSaveableObject.ISaveableRestoreScene(SceneManager.GetActiveScene().name);
+        }
+    }
}


```


## ISaveable

```diff_c_sharp:ISaveable.cs
public interface ISaveable
{
    string ISaveableUniqueID { get; set; }
    
    GameObjectSave GameObjectSave { get; set; }

    void ISaveableRegister();

    void ISaveableDeregister();

    void ISaveableStoreScene(string sceneName);

+    void ISaveableRestoreScene(string sceneName);
}


```


## SceneItemManager

```diff_c_sharp:SceneItemManager.cs
using System.Collections.Generic;
using UnityEngine;


[RequireComponent(typeof(GenerateGUID))]
public class SceneItemsManager : SingletonMonobehaviour<SceneItemsManager>,ISaveable
{
    private Transform parentItem;
    [SerializeField] private GameObject itemPrefab = null;
    private string _iSaveableUniqueID;
    public string ISaveableUniqueID
    {
        get { return _iSaveableUniqueID; }
        set {_iSaveableUniqueID = value; }
    }

    private GameObjectSave _gameObjectSave;
    public GameObjectSave GameObjectSave
    {
        get { return _gameObjectSave;}
        set { _gameObjectSave = value;}
    }
+    private void DestroySceneItems()
+    {
+        Item[] itemsInScene = GameObject.FindObjectsOfType<Item>();
+        for (int i = itemsInScene.Length - 1; i > -1; i--)
+        {
+            Destroy(itemsInScene[i].gameObject);
+        }        
+    }
+    private void InstantiateSceneItems(List<SceneItem> sceneItemList)
+    {
+        GameObject itemGameObject;
+        foreach (SceneItem sceneItem in sceneItemList)
+        {
+            itemGameObject = Instantiate(itemPrefab,
+                new Vector3(sceneItem.position.x, sceneItem.position.y, sceneItem.position.z), Quaternion.identity,
+                parentItem);
+            Item item = itemGameObject.GetComponent<Item>();
+            item.ItemCode = sceneItem.itemCode;
+            item.name = sceneItem.itemName;
+        }
+    }
+    public void ISaveableRestoreScene(string sceneName)
+    {
+        if (GameObjectSave.sceneData.TryGetValue(sceneName, out SceneSave sceneSave))
+        {
+            if (sceneSave.listSceneItemDictionary != null &&
+                sceneSave.listSceneItemDictionary.TryGetValue("sceneItemList", out List<SceneItem> sceneItemList))
+            {
+                DestroySceneItems();
+                InstantiateSceneItems(sceneItemList);
+            }
+        }
+    }    
}
```


# 参考

## C#

## Unity Editor コンポーネント

## Unity スクリプト

## その他

Sectioin10 42

https://www.udemy.com/course/unity-2d-game-developer-course-farming-rpg/learn/lecture/19849494#content

github コミット分（個人確認用　privateなので見れません）

https://github.com/RYA234/LearnFarmRPG/commit/b5284f8ee86bc9d8eca6165a1fc34ecc8ce3d55f