微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我无法在主菜单上保存多个 PlayerPrefs

如何解决我无法在主菜单上保存多个 PlayerPrefs

您好,我是游戏开发专业的学生,​​正在制作一款游戏,玩家可以在每张地图上获取一定数量的硬币,每张地图都有不同类型的硬币数据,例如高分。但它只保存 1 个玩家偏好设置。为什么会这样?

这是我的场景管理脚本;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using TMPro;

public class changeScene : MonoBehavIoUr
{
    public TextMeshProUGUI desertCoinAmount;
    public TextMeshProUGUI plainsCoinAmount;

    void Update()
    {
        desertCoinAmount.text = PlayerPrefs.GetInt("DesertCoins").ToString();
        plainsCoinAmount.text = PlayerPrefs.GetInt("PlainsCoins").ToString();
    }

    public void mainMenu()
    {
        SceneManager.LoadScene("mainMenu");
        PlayerPrefs.Save();
    }

    public void desertLevel()
    {
        SceneManager.LoadScene("ancientDesertLEVEL");
        Time.timeScale = 1f;
        PlayerPrefs.Save();
    }
    public void plainsLevel()
    {
        SceneManager.LoadScene("Plain Biome");
        Time.timeScale = 1f;
        PlayerPrefs.Save();
    }
    
    public void jungleLevel()
    {
        SceneManager.LoadScene("Jungle Biome");
        Time.timeScale = 1f;
    }
}

这是我的 PlayerController;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class PlayerController : MonoBehavIoUr
{
    public GameObject winPopup,losePopup;
    public GameObject heart1,heart2,heart3;
    public float gravityScale = 10f;
    private Rigidbody rb;
    public TextMeshProUGUI coinText;
    public AudioSource coinSound;

    int coin_sumDesert;
    int coin_sumPlains;
    int life_sum = 3;


    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        GetComponent<Rigidbody>().AddForce(Physics.gravity * gravityScale,ForceMode.Force);
    }

   void Update()
    {
        PlayerPrefs.SetInt("DesertCoins",coin_sumDesert);
        PlayerPrefs.SetInt("PlainsCoins",coin_sumPlains); 
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.tag == "Coins")
        {
            coin_sumDesert++;
            coinText.text = coin_sumDesert.ToString();
            Destroy(other.gameObject);
            coinSound.Play();
            
        }
        
        if (other.gameObject.tag == "PlainsCoins")
        {
            coin_sumPlains++;
            coinText.text = coin_sumPlains.ToString();
            Destroy(other.gameObject);
            coinSound.Play();
            
        }
        
        if (other.gameObject.tag == "finishLine")
        {
            winPopup.SetActive(true);
            
        }

        if (other.gameObject.tag == "obstacles")
        {
            Debug.Log("Collide Detected");
            life_sum--;
            if (life_sum == 2)
            {
                heart1.SetActive(false);
            }
            else if (life_sum == 1)
            {
                heart2.SetActive(false);
            }
            else if (life_sum == 0)
            {
                heart3.SetActive(false);

                losePopup.SetActive(true);
                Time.timeScale = 0.0f;
               
            }
        }
    }
}

感谢您的回复(这是我第一次使用 StackOverflow xD)

解决方法

如果您有多个 PlayerController,那么显然它们会写入相同的 PlayerPrefs 键。

每当您保存玩家的数据时,请确保区分它们,例如分数 1、分数 2 等

这是实现它的许多其他方法之一:

播放器,非常简单,将索引附加到播放器首选项以区分多个:

public sealed class Player : MonoBehaviour
{
    private const string ChocolateBarsKey = "ChocolateBars";

    [SerializeField]
    [HideInInspector]
    private int Index;

    private int ChocolateBars
    {
        get => GetInt(ChocolateBarsKey);
        set => SetInt(ChocolateBarsKey,value);
    }

    private int GetInt([NotNull] string key,int defaultValue = default)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));

        return PlayerPrefs.GetInt($"{key}{Index}",defaultValue);
    }

    private void SetInt([NotNull] string key,int value)
    {
        PlayerPrefs.SetInt($"{key}{Index}",value);
    }

    [NotNull]
    internal static Player Create([NotNull] GameObject parent,int index)
    {
        if (parent == null)
            throw new ArgumentNullException(nameof(parent));

        var controller = parent.AddComponent<Player>();

        controller.name  = $"{nameof(Player)} {index}";
        controller.Index = index;

        return controller;
    }
}

工厂、可编写脚本的单例不会在程序集重新加载时丢失状态,而如果您使用静态 int 来计算玩家数量,它会在程序集重新加载时将自身重置为零,因为静态字段不会被序列化团结。

public sealed class PlayerFactory : ScriptableSingleton<PlayerFactory>
{
    [SerializeField]
    private int PlayerCount;

    [NotNull]
    public Player Create(GameObject parent)
    {
        return Player.Create(parent,++PlayerCount);
    }
}

现在,如果您不想将分数数据存储在 Player 中,那将是另一种模式。我把它留给你作为练习。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。