ステージ解放の実装
unity1weekに参加しました。今回のテーマは「密」です。
磁石の力で壁に密着したり、逆に反発の力で飛んだり、、、という
引っ張りアクションゲームです。

【投稿した作品】:MAGNET MONSTER
そのゲームの中で
あるステージをクリアすると遊べるようになるステージが出現する実装
に試みました。
次遊ぶとき(ブラウザを閉じて再度読み込んだとき)にも
前回のクリアデータは保持されるという前提もクリアしたかったです。
PlayerPrefs
今回はPlayerPrefsを使った実装を行いました。
理由としては、手軽さ、ただそれだけです。
多くのデータを保存したり、
改変、閲覧されて困る情報を保存するのには向いていないそうですが、
今回はあまり関係が無いのでセーフです。
実装の詳細
ステージをクリアするまでは
Easyモード以外は???という項目となっており、
選択しても遊べません。

クリア後の画像が下記画像です。
Easyモード以外の項目の文字が???から変更されており、
選択して遊ぶことができます。
 
コード
**情報を保存する側(SetIntする側)**と
**保存された情報を取り出す側(GetInt)**が必要です。
PlayerPrefs.SetInt
まずは**情報を保存する側(SetIntする側)**を見ていきます。
private void OnCollisionEnter(Collision other)
{
    if (other.gameObject.layer == LayerMask.NameToLayer("Goal"))
    {
        //どのシーンをクリアしたかでSetIntする数字を変更
        if (SceneManager.GetActiveScene().name == "EasyScene")
        {
            PlayerPrefs.SetInt ("LEVEL", 1);
        }   
        else if (SceneManager.GetActiveScene().name == "NormalScene")
        {
            PlayerPrefs.SetInt ("LEVEL", 2);
        }
        else if (SceneManager.GetActiveScene().name == "HardScene")
        {
            IsClearHardThisTime = true;
            PlayerPrefs.SetInt ("LEVEL", 3);
        }
        
        //念のためセーブしとく クラッシュすることあるらしい
        PlayerPrefs.Save();
    }
}
下記画像のようにプレイヤーがゴールに衝突した瞬間に
今開いているシーンを参照してセットする値を決めています。
 
PlayerPrefs.GetInt
**保存された情報を取り出す側(GetInt)**です。
using UnityEngine;
using UnityEngine.UI;    
    
public class TitleSceneManager : MonoBehaviour
{
    [SerializeField] private Image _normalImage;
    [SerializeField] private Image _hardImage;
    [SerializeField] private Image _rankingImage;
    [SerializeField] private Sprite _normalSprite;
    [SerializeField] private Sprite _hardSprite;
    [SerializeField] private Sprite _rankingSprite;
    
    private void Start()
    { 
        int clearLevel = PlayerPrefs.GetInt("LEVEL",0);
        //レベルに応じてUI画像入れ替え
        switch (clearLevel)
        {
            case 1:
                _normalImage.sprite = _normalSprite;
                break;
            case 2:
                _normalImage.sprite = _normalSprite;
                _hardImage.sprite = _hardSprite;
                break;
            case 3:
                _normalImage.sprite = _normalSprite;
                _hardImage.sprite = _hardSprite;
                _rankingImage.sprite = _rankingSprite;
                break;
        }
    }
}
タイトルシーンの読み込み時に
保存されたステージクリアの情報を取得して、
画像の差し替えを行っています。
あとはステージ選択ボタンを押したら、、、という処理に
if文でReturn処理を書くなどすればボタンの選択も制限できます。
PlayerPrefs.Save
このSaveのタイミング、どうやらタイミング次第では
たまにデータが吹き飛ぶことがあるそうなので
SetIntするたびにPlayerPrefs.Save();を
呼び出しておいた方がよさそうです
【参考リンク】:Playerprefsを確実に保存するリンク
デバッグ時のリセット
# if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
/// <summary>
/// PlayerPrefsを初期化するクラス
/// </summary>
public static class PrefsClear
{
    [MenuItem("Tools/Reset PlayerPrefs")]
    public static void ResetPlayerPrefs()
    {
        PlayerPrefs.DeleteAll();
        PlayerPrefs.Save();
        Debug.Log("Reset PlayerPrefs");
    }
}
# endif
下記参考リンクから頂戴しました。
【参考リンク】:PlayerPrefsをリセットするメニューを追加する【Unity】【エディタ拡張】
クリアしたデータはEditor上での実行時にも保存されるので
削除する機能があるとデバッグがはかどります。
最後に
私はこういう実装でやってますというのがあれば教えてください。
初めての試みなので、なんか動いたからヨシ!って感じです。
