【问题标题】:"How to fix PlayerPrefs not saving or loading saved data"“如何修复 PlayerPrefs 不保存或加载保存的数据”
【发布时间】:2019-05-11 19:59:39
【问题描述】:

所以我正在为我的蛇游戏使用定制器,并且我正在使用 PlayerPrefs 来保存蛇的偏好外观。现在,每次我测试运行游戏时,playerprefs 中保存的字符串都不会加载,它只是空的。

我已经尝试在 Start()、Awake() 和 Update() 方法中获取字符串数据,但它们都没有加载数据。我还在保存数据的每一行中添加了 PlayerPrefs.Save()。

这是我将所有网格更新为与保存的字符串相同的代码。我已经把它放在了更新方法中。

lesnek = GameObject.FindGameObjectsWithTag("LeWorm");

        objName = PlayerPrefs.GetString("meshName");

        if (PlayerPrefs.HasKey("meshName"))
        {
            if (objName == PlayerPrefs.GetString("meshName"))
            {
                leMesh = Resources.Load<GameObject>(@"Models\" + objName);
            }
            else
            {
                objName = PlayerPrefs.GetString("meshName");
                leMesh = Resources.Load<GameObject>(@"Models\" + objName);
            }
        }
        if (objName != null || objName != "")
        {
            objName = "Sphere";
            leMesh = Resources.Load<GameObject>(@"Models\" + objName);
        }

        foreach (GameObject change in lesnek)
        {
            if (objName != null || objName != "")
            {
                if (change.GetComponent<MeshFilter>() == null)
                {
                    change.AddComponent<MeshFilter>();
                    change.GetComponent<MeshFilter>().mesh = leMesh.GetComponent<MeshFilter>().sharedMesh;
                    PlayerPrefs.SetString("meshName", objName);
                    PlayerPrefs.Save();
                }
                else
                {
                    change.GetComponent<MeshFilter>().mesh = leMesh.GetComponent<MeshFilter>().sharedMesh;
                    PlayerPrefs.SetString("meshName", objName);
                    PlayerPrefs.Save();
                }
            }
        }

每次运行此代码时,我都会收到错误消息,并且不会在 playerprefs 中加载或保存字符串。

【问题讨论】:

  • 如果您遇到错误,请向我们提供错误消息。
  • 因此,如果我删除此 if (objName != null || objName != "") 语句,我会收到以下错误消息:UnassignedReferenceException:ChangerPasserScript 的变量 leMesh 尚未分配。您可能需要在检查器中分配 ChangerPasserScript 脚本的 leMesh 变量。 UnityEngine.GameObject.GetComponent[MeshFilter] () (在 C:/buildslave/unity/build/Runtime/Export/GameObject.bindings.cs:28) ChangerPasserScript.Update () (在 Assets/Scripts/ChangerPasserScript.cs:52)
  • 好吧,resource.load 是正确的,我试图通过在控制台中打印来获取字符串,但它什么也没打印

标签: c# unity3d


【解决方案1】:

这里有一些问题,你的空引用错误是主要的原因。

我会评论你的代码,告诉你哪里出了问题并提供替代解决方案。

// If possible it would be better to assign this object in the inspect rather then 
// using a GameObject.Find method, Also this is error prone due to the timing of 
// the call, for example if this is in a start this Object may not exist yet.
// Another solution would to be create an event and when you load the skin
// Have that event fire off that its been loaded and everything that needs
// to listen to it will get the change.
lesnek = GameObject.FindGameObjectsWithTag("LeWorm");

//  GetString has an alternative method where you can pass a default value
//  I would recommend using this method instead.
objName = PlayerPrefs.GetString("meshName");    // POINT A

// Honestly this check seems a tad bit redundant since you already
// attempted to load this preference.
// POINT B
if (PlayerPrefs.HasKey("meshName"))  // Since you have said this is empty playerPrefs is empty.
{
    // At this point it should equal this since you already set it to this in Point A
    if (objName == PlayerPrefs.GetString("meshName"))
    {
        leMesh = Resources.Load<GameObject>(@"Models\" + objName);
    }
    else
    {
        // This case should never get called, because of Point A and your if condition.
        objName = PlayerPrefs.GetString("meshName");
        leMesh = Resources.Load<GameObject>(@"Models\" + objName);
    }
}

if (objName != null || objName != "")  // This completely nullifies all the work in Point B
{
    objName = "Sphere";
    leMesh = Resources.Load<GameObject>(@"Models\" + objName);
}
foreach (GameObject change in lesnek)
{
    if (objName != null || objName != "")
    {
        if (change.GetComponent<MeshFilter>() == null)
        {
            change.AddComponent<MeshFilter>();
            change.GetComponent<MeshFilter>().mesh = leMesh.GetComponent<MeshFilter>().sharedMesh;
            PlayerPrefs.SetString("meshName", objName);
            PlayerPrefs.Save();
        }
        else
        {
            change.GetComponent<MeshFilter>().mesh = leMesh.GetComponent<MeshFilter>().sharedMesh;
            PlayerPrefs.SetString("meshName", objName);
            PlayerPrefs.Save();
        }
    }
}

不做太多细节,假设这是一种初始化方法的形式,而不是开始,这是我要做的改变

// This would be better as a class variable rather then a local variable
string meshName = PlayerPrefs.GetString("meshName", "Sphere");  
// Skipping point B because it is redundant
leMesh = Resources.Load<GameObject>(@"Models\" + meshName);  // Is this a GameObject or is it a Mesh???

MeshFilter leMeshFilter = leMesh.GetComponent<MeshFilter>();
if(leMeshFilter != null)
{
    foreach (GameObject change in lesnek)
    {
        MeshFilter meshFilter = change.GetComponent<MeshFilter>();
        if(meshFilter != null)
        {
            meshFilter.mesh = leMeshFilter.sharedMesh;
        }
        else
        {
            meshFilter = change.AddComponent<MeshFilter>();
            meshFilter.mesh = leMeshFilter.sharedMesh;
        }
    }
}

这个例子唯一没有做的就是保存你的 PlayerPreference。这是只有在更换皮肤时才应该做的事情。因此,无论您做什么,都可以保存偏好。

【讨论】:

  • 谢谢,还没有尝试过,但我有一个问题.. pp 是否需要大量内存来加载?
  • @Zacqwerty 我从来没有遇到过占用大量内存的问题。
  • 没用它只是像我的工作一样工作保存字符串没有laod
  • @Zacqwerty 那么你一定是在meshName中保存了一个空字符串。如果PlayerPrefs 中不存在该字符串,它将返回 Sphere,如果它返回一个空字符串,则该键存在,其中没有任何内容。清除您的偏好可能是个好主意
  • 在某处使用PlayerPrefs.DeleteKey("meshName") 运行您的项目,然后在没有它的情况下重新启动您的项目。
【解决方案2】:

找不到游戏对象“leMesh”。第一步是确保它确实被找到。所以让我们确保我们知道它的状态以便调试它:

if (PlayerPrefs.HasKey("meshName"))
    {
        Debug.Log("PlayerPrefs does have the key we are looking for and it is " + PlayerPrefs.GetString("meshName"));

        /// This is redundant you just set objName to the string earlier
        /// objName = PlayerPrefs.GetString("meshName");
        if (objName == PlayerPrefs.GetString("meshName"))
        {
            leMesh = Resources.Load<GameObject>(@"Models\" + objName);
        }
        else
        {
            /// And here you do it again, constantly trying to get that string
            /// In order to find the object, of course if the string doesnt exist
            /// youll simply get an unassigned referenceException on this line:
            /// change.GetComponent<MeshFilter>().mesh = leMesh.GetComponent<MeshFilter>().sharedMesh
            objName = PlayerPrefs.GetString("meshName");
            leMesh = Resources.Load<GameObject>(@"Models\" + objName);
        }
    }

现在,如果您的控制台日志告诉您 meshName 返回一个值,那么您访问的资源有误,在这种情况下尝试从“Models”前面删除“@”。否则没有名为 meshName 的 playerPrefs 字符串。

ref

【讨论】:

  • 是的,我知道,无论如何感谢缩短我的冗余代码,但我的问题是 PlayerPrefs 好的,所以我现在有了这个 meshName pp/playerprefs,我保存了一个字符串,每次我更改网格名称时网格现在在加载或获取 mehsName pp 时,它总是在控制台中显示“”。只是空白.....
  • 另外我一直在猜测为什么 pp 没有得到字符串是因为它像重负载一样占用了系统大量内存
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多