首页 > 解决方案 > 尽管我在 android 上使用“HasKey”和 Save(),为什么 PlayerPrefs 不起作用?

问题描述

我知道其他人以前写​​过这个问题,但即使我使用 haskey 或保存我的 android 设备也不会保存数据。顺便说一句,它在 PC 上工作正常。

 public class PlayerData : MonoBehaviour
 {
     public float HighScore { get; set; }
   
 }

用于保存和加载的其他脚本

public class PlayerPersistence : MonoBehaviour
 {
    
     public static void SavePlayerHighScore(float highScore)
     {
         if (PlayerPrefs.HasKey("HighScore"))
         {
             Debug.Log("has key");
         }
         else
         {
             PlayerPrefs.SetFloat("HighScore", highScore);
             PlayerPrefs.Save();
         }
         
 
     }
 
     public static PlayerData LoadData()
     {
        
         float highScore = PlayerPrefs.GetFloat("HighScore", 0);
         PlayerPrefs.Save();
         PlayerData playerData = new PlayerData()
         {
            
             HighScore = highScore
         };
         return playerData;
     }
 }

像这样打电话

 public PlayerData playerData { get; private set; }
 
   private void Awake()
     {
         playerData = PlayerPersistence.LoadData();
         HighScore();
         t.text = playerData.HighScore.ToString();
     }

编辑:计时器实际上是分数,如果小于 highScore(保存的数据)正在用旧数据更改新的,这就是我调用类的方式

public PlayerData playerData { get; private set; }

private void Awake()
    {
      
        playerData = PlayerPersistence.LoadData();
        
    }
 
if(finish){
  if (timer < playerData.HighScore)
            {
                PlayerPersistence.SavePlayerHighScore(timer); // last score;
                playerData = PlayerPersistence.LoadData();
                bestTime.text = "Best Time: " + playerData.HighScore.ToString();
            }
            else
            {
                bestTime.text = "Best Time: " + playerData.HighScore.ToString();
            }
}

标签: c#unity3d

解决方案


首先:如果您对纯数据容器进行分类而不需要附加到游戏对象,那么它们不应该是MonoBehaviour!特别是在 Unity 中禁止new使用for MonoBehaviour。(参见例如为什么我会收到警告:您正在尝试使用“new”关键字创建“MonoBehaviour”

它应该是

// Use Serializable and fields instead of properties
// So you can actually see the values in the Unity inspector!
[Serializable]
public class PlayerData
{
    public float HighScore;
}

// This class can even be static since it only contains static members 
// and never needs/means to be instantiated
public static class PlayerPersistence
{
    ...    
}

那么,如果到目前为止还没有高分,为什么你只保存一个新的高分呢?您不想检查新的高分是否更高,然后覆盖现有的高分吗?也不需要使用PlayerPrefs.Saveafter GetInt;)

public static class PlayerPersistence
{
    // Optional parameter: if you don't pass it in it will always assume false by default
    public static void SavePlayerHighScore(float highScore, bool forceOverwrite = false)
    {
        if (!forceOverwrite && PlayerPrefs.HasKey("HighScore"))
        {
            Debug.Log("has key -> check if higher");
            var currentScore = PlayerPrefs.GetFloat("HighScore");
            if(currentScore >= highScore)
            {
                Debug.LogWarning("Current HighScore is higher -> will not overwrite");
                return;
            }
         }     
         
         Debug.Log("Saving new Highscore");
         PlayerPrefs.SetFloat("HighScore", highScore);
         PlayerPrefs.Save();
     }
 
     public static PlayerData LoadData()
     {
         var highScore = PlayerPrefs.GetFloat("HighScore", 0);

         PlayerData playerData = new PlayerData()
         {  
             HighScore = highScore
         };

         return playerData;
     }
 }

最后应该是

[SerializeField] private PlayerData _playerData;

public PlayerData PlayerData => _playerData;

private void Awake()
{
    _playerData = PlayerPersistence.LoadData();

    HighScore();
    t.text = _playerData.HighScore.ToString();
}

现在它当然仍然取决于SavePlayerHighScore您没有向我们展示的确切调用方式。


推荐阅读