如何解决将 Image.fillAmount 保存在变量/PlayerPrefs 等中
我有一个如下图所示的进度条,它会在每个级别完成后添加一定数量的 Image.fillAmount
。我如何保存填充量,我是否将它存储在另一个变量中,使用 Player Prefs 或什么?尝试解释:
Level 1 完成后加一颗星
第 2 级完成后会再增加一颗星等等:
这是我在 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 举报,一经查实,本站将立刻删除。