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

将 Image.fillAmount 保存在变量/PlayerPrefs 等中

如何解决将 Image.fillAmount 保存在变量/PlayerPrefs 等中

我有一个如下图所示的进度条,它会在每个级别完成后添加一定数量Image.fillAmount。我如何保存填充量,我是否将它存储在另一个变量中,使用 Player Prefs 或什么?尝试解释:

Level 1 完成后加一颗星

enter image description here

第 2 级完成后会再增加一颗星等等:

enter image description here

这是我在 LevelControl 中添加 fillAmount 的代码的一部分:

private void LvlFinish()
    {
        loupe.GetComponent<Collider>().enabled = false;
        WinPanel.transform.SetAsLastSibling();
        WinPanel.SetActive(true);
        stars.fillAmount = 0.1f;
        PlayerPrefs.SetFloat("Progress",amount);
        PlayerPrefs.Save();
        Debug.Log(PlayerPrefs.GetFloat("Progress",0));
}

我尝试使用 PlayerPrefs 保存它,但没有成功。

左边是关卡选择面板,右边是关卡完成后的面板。

解决方法

您需要获取当前进度值,然后在保存之前添加 0.1f(或您想要的任何值)。现在,您始终将“fillAmount”设置为 0.1f。

   // Get the stored value. (I assume "amount" is a float variable)
   amount = PlayerPrefs.GetFloat("Progress",0);
   // Add 10%
   amount += 0.1f;
   // Store the new value
   PlayerPrefs.SetFloat("Progress",amount);
   PlayerPrefs.Save(); 
   // Update the stars image
   stars.fillAmount = amount

这将确保在会话之间保存进度。

但是,请注意 PlayerPerfs 不是存储进度数据的安全位置。用户可以很容易地手动编辑这些值。如果您将数据手动存储在 Application.persistentDataPath 中,则其他人更难查看/更改值。它实际上并不是使它“更安全”的位置,但现在你必须自己序列化/反序列化它,因此你可以用二进制来完成,甚至添加一些简单的加密 - 好吧,二进制通常足以让大多数玩家远离。 ..

[已添加] 这是我用来将对象序列化/反序列化到持久存储的静态类。当然有数百种方法可以做到这一点,只需谷歌就可以了,但这对我来说很好用,而且非常强大。它没有加密,但二进制通常足够好(见评论)。

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;

/// <summary>
/// Tools to serialize and deserialize objects.
/// </summary>
public static class PersistenceTools
{
    /// <summary>
    /// Saves an object to the persistent storage.
    /// </summary>
    /// <param name="name">The name of the file.</param>
    /// <param name="data">The object to serialize.</param>
    public static void Save(string name,object data)
    {
        string filePathNameData = System.IO.Path.Combine(Application.persistentDataPath,name) + ".dat";
        string filePathNameBakup = filePathNameData + "-bak";

        // Remove the old backup-file (if it exists) and rename the current (if it exists) to the backup name. 
        if (System.IO.File.Exists(filePathNameBakup))
            System.IO.File.Delete(filePathNameBakup);
        if (System.IO.File.Exists(filePathNameData))
            System.IO.File.Move(filePathNameData,filePathNameBakup);

        BinaryFormatter binaryFormatter = new BinaryFormatter();
        using (FileStream fileStream = new FileStream(filePathNameData,FileMode.Create))
        {
            binaryFormatter.Serialize(fileStream,data);
        }
    }

    /// <summary>
    /// Loads an object from the persistent storage.
    /// </summary>
    /// <typeparam name="L">The type of object we expect to deserialize.</typeparam>
    /// <param name="name">The name of the file to load (no path).</param>
    /// <returns></returns>
    public static L Load<L>(string name)
    {
        string filePathNameData = System.IO.Path.Combine(Application.persistentDataPath,name) + ".dat";
        string filePathNameBakup = filePathNameData + "-bak";

        try
        {
            return InternalLoad<L>(filePathNameData);
        }
        catch (Exception ex1)
        {
            if (System.IO.File.Exists(filePathNameData))
                Debug.LogError("Could not read the file \"" + filePathNameData + "\". " + ex1.Message);
            try
            {
                return InternalLoad<L>(filePathNameBakup);
            }
            catch (Exception ex2)
            {
                if (System.IO.File.Exists(filePathNameBakup))
                    Debug.LogError("Could not read the file \"" + filePathNameBakup + "\". " + ex2.Message);
                return default(L);
            }
        }
    }

    /// <summary>
    /// Internal method to do the actual deserialization.
    /// </summary>
    /// <typeparam name="L">The type of object we expect to deserialize.</typeparam>
    /// <param name="filePathName">The file with path to deserialize.</param>
    /// <returns></returns>
    private static L InternalLoad<L>(string filePathName)
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        using (FileStream fileStream = new FileStream(filePathName,FileMode.Open))
        {
            return (L) binaryFormatter.Deserialize(fileStream);
        }
    }

    /// <summary>
    /// Deletes a file,including any backup version,from the persistent datastorage.
    /// </summary>
    /// <param name="name">The name of the file to delete (no path),</param>
    public static void Delete(string name)
    {
        string filePathNameData = System.IO.Path.Combine(Application.persistentDataPath,name) + ".dat";
        string filePathNameBakup = filePathNameData + "-bak";

        // Remove the files. 
        if (System.IO.File.Exists(filePathNameBakup))
            System.IO.File.Delete(filePathNameBakup);
        if (System.IO.File.Exists(filePathNameData))
            System.IO.File.Delete(filePathNameData);
    }
}

为了能够自动序列化/反序列化一个对象,它必须被声明为“[Serializable]”。这是一个非常简单的用户槽示例,用于跟踪用户的姓名和当前分数。

[Serializable]
public class UserSlot
{
    public string UserName { get; set; }
    public int Score { get; set; }
}

这是一个例子:

// Create a slot and set some values.
UserSlot userSlot = new UserSlot() { UserName = "Andulf Games",Score = 13 };

...

// Save the slot (the filename will be "Slot1.dat").
PersistenceTools.Save("Slot1",userSlot);

稍后加载您只需调用的信息:

UserSlot userSlot = PersistenceTools.Load<UserSlot>("Slot1");

如您所见,每次保存时,我们都会自动将当前文件重命名为 .bak 并生成一个新的 .dat 文件。如果我们在保存时崩溃,或者数据损坏,我们总是准备好备份文件。

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