使用播放器首选项读取和写入数据

更新页 :
页面创建日期 :

验证环境

窗户
  • 视窗 11
统一编辑器
  • 2021.3.3f1
输入系统包
  • 1.3.0

此提示的先决条件

作为此提示描述的前提,已预先进行了以下设置。

起先

如果你玩过游戏,你们中的大多数人都经历过。 您可能已暂停游戏并保存或加载了游戏数据以将其关闭。

创建游戏时,通常需要创建此保存和加载功能,设置选项等。 在这里,我们将尝试使用最简单的 PlayerPrefs 方法来存储和加载数据来实现这一点。

用户界面放置

在这里,我们将尝试通过放置输入项和按钮并单击按钮来保存或读取输入内容。 目前,您只需要至少两个按钮和一个输入字段,因此请随意放置它们。

准备 UI 处理

首先,让我们实现保存按钮。 如何创建按钮事件在下面的提示中介绍,所以我只列出相关部分。

将脚本名称 ButtonEvent 保留为 。

脚本如下所示:

using UnityEngine;
using UnityEngine.UI;

public class ButtonEvent : MonoBehaviour
{
  /// <summary>名前入力フィールド。</summary>
  [SerializeField] InputField InputFieldName;

  /// <summary>HP 入力フィールド。</summary>
  [SerializeField] InputField InputFieldHP;

  /// <summary>攻撃力入力フィールド。</summary>
  [SerializeField] InputField InputFieldAttack;

  /// <summary>お金入力フィールド。</summary>
  [SerializeField] InputField InputFieldMoney;

  /// <summary>
  /// 保存ボタンをクリックしたときの処理。
  /// </summary>
  public void OnClickSave()
  {
  }

  /// <summary>
  /// 読み込みボタンをクリックしたときの処理。
  /// </summary>
  public void OnClickLoad()
  {
  }
}

由于需要获取或设置输入的值,因此请将其准备为字段。 此外,还包括单击每个按钮时将调用的方法。

EventSystem 脚本附加到并设置每个输入字段。 它可以是您要附加的任何对象。

设置单击按钮时要调用的每个方法。

保存值

现在,单击保存按钮时 OnClickSave 调用该方法,保存按钮的过程如下所示。

/// <summary>
/// 保存ボタンをクリックしたときの処理。
/// </summary>
public void OnClickSave()
{
  // 各値を指定したキーに保存します
  PlayerPrefs.SetString("Name", InputFieldName.text);
  PlayerPrefs.SetString("HP", InputFieldHP.text);
  PlayerPrefs.SetString("Attack", InputFieldAttack.text);
  PlayerPrefs.SetString("Money", InputFieldMoney.text);

  // 設定したデータを確定して保存します
  PlayerPrefs.Save();
}

PlayerPrefs.SetString 该方法设置为要保存的键和值。 键是在加载保存的数据时指定的。 SetString 这里我们调用该方法,因为要存储的值是一个字符串。 int float 如果要 SetInt 保存其他类型的值,例如 和 ,则有诸如 和 SetFloat 之类的方法,因此请根据类型调用它们。

PlayerPrefs.Save最后,调用该方法以确认保存。 实际上,即使您不调用此方法,它也可以保存,但调用它更安全。

但是,即使您此时运行游戏,它也只会保存值,因此您将不知道它是否正确保存。 如果您检查保存的位置,您可以看到数据,但是...

获取保存的值

接下来,实现加载保存数据的过程。 按钮的处理与保存过程相同,因此此处仅介绍加载过程的代码。

/// <summary>
/// 読み込みボタンをクリックしたときの処理。
/// </summary>
public void OnClickLoad()
{
  // 指定したキーから値を読み込みます
  InputFieldName.text = PlayerPrefs.GetString("Name");
  InputFieldHP.text = PlayerPrefs.GetString("HP");
  InputFieldAttack.text = PlayerPrefs.GetString("Attack");
  InputFieldMoney.text = PlayerPrefs.GetString("Money");
}

使用该方法 PlayerPrefs.GetString 加载保存的数据。 可以通过指定在另存为参数中指定的键来获取使用该键保存的值。 该值在方法的返回值中检索。

这也以与保存时相同的方式保存为字符串,因此GetString我们调用该方法。 intGetFloat GetIntfloat如果使用 或 保存,请调用该方法。

检索到的值将反映在输入字段中。

您现在可以保存和加载数据。 我认为没有任何困难的元素。

尝试移动它

运行以输入、保存和加载。 保存的数据将保留,即使您退出并重新运行游戏,也应该能够加载。 如果您可以确认以下模式,我认为没有问题。

  1. 输入一个值
  2. 单击保存按钮
  3. 更改您输入的值
  4. 单击导入按钮以确认它返回到保存的值。
  5. 退出游戏
  6. 重新运行游戏并单击加载按钮以查看是否可以调用保存的值
  7. 输入不同的值,保存它,然后检查是否可以使用更新的值读取相同的值

保存和加载数据块

在到目前为止的示例中,仅保存了几个参数。 当你实际制作一个游戏时,要保存的参数数量会稳步增加,如果你一个一个地读写它们,代码将是巨大的。 因此,在创建要实际保存的数据时,理论是将要保存的数据合并为一个,然后一次全部写入。

首先,将数据结构保存为类。 目标是能够一次读取和写入数据,但也对数据进行分类,以使代码更容易访问每段数据。

以下是保存游戏类的示例: 它可以写在任何可以从其他代码引用的地方。 此类结构是一个示例,因此在实际游戏中,您需要为游戏创建它。

/// <summary>セーブデータクラス。</summary>
public class SaveData
{
  public List<Character> Characters;
  public long Money;
}

/// <summary>1キャラクターの情報。</summary>
[Serializable]
public class Character
{
  public string Name;
  public int HP;
  public int Attack;
}

在这次使用的 Unity 标准函数中 List ,如果定义数组或具有多个唯一类, System.Serializable 如果不添加属性,它将无法正确转换,因此 Character 我将属性设置为 Serializable 类。

创建类后,创建要保存的数据。 当然,您可以在整个游戏中拥有此类的实例。 这取决于游戏的制作方式。

// 保存するデータ作成
var saveData = new SaveData
{
  Money = 10000,
  Characters = new List<Character>
  {
    new Character { Name= "レイシア", HP = 50, Attack = 40, },
    new Character { Name= "アイリ", HP = 56, Attack = 27, },
    new Character { Name= "ニール", HP = 72, Attack = 36, },
    new Character { Name= "トリー", HP = 61, Attack = 30, },
  },
};

在类的实例中设置 JsonUtility.ToJson 数据后,使用该方法将其转换(序列化)为 JSON 字符串。 由于对象的值是具有数据结构的称为 JSON 的单个“字符串”,因此可以通过对该方法的一次调用来写入所有PlayerPrefs.SetString 数据。

// オブジェクトを JSON 文字列に変換します
var saveJson = JsonUtility.ToJson(saveData);

// データを保存します
PlayerPrefs.SetString("SaveData", saveJson);
PlayerPrefs.Save();

但是,由于所有数据都收集在一个数据中,因此不可能仅保存其中的一部分或仅读取其中的一部分。 因此,最好将其设置为易于汇总的单元,例如将其组合为一个保存数据的一个对象。

读取保存的数据时,可以在保存时进行反向处理。 要读取的数据是单个字符串,但内容是 JSON 格式的数据结构,因此 JsonUtility.FromJson 可以通过方法将它们转换(反序列化)为类实例。 但是,由于字符串中没有 FromJson 要转换为哪个类的信息,因此我们必须在调用方法时指定类型。

// データを読み込みます
var loadJson = PlayerPrefs.GetString("SaveData");

// JSON 文字列からオブジェクトにデシリアライズします
var newData = JsonUtility.FromJson<SaveData>(loadJson);

如果您尝试移动它,您可以看到它已正确保存并且可以加载。

顺便说一下,我们这次使用的是 Unity 标准 JsonUtility 类,但它们可能无法转换具有复杂数据结构的类,因为它们的功能不是很好。 在这种情况下,建议使用其他库。

数据存储在哪里?

PlayerPrefs 使用类存储数据时,保存数据的位置取决于运行数据的平台。 请参阅下面的官方页面,了解实际存储的位置。

在某些环境(如 Windows)中,它们不存储在文件中,而是存储在注册表等系统设置中。 由于它不是文件,因此不适合将保存的数据保存在 中,例如,如果保存的数据非常大,或者 PlayerPrefs 您希望将保存数据与另一个环境同步。 相反,如果要保存的数据是选项级别的大小,或者如果它是仅在运行环境中完成的独立游戏, PlayerPrefs 我认为可以将数据保存在.

此外,保存位置的路径可能会受到“公司名称”和“产品名称”设置的影响。 如果要发布游戏,则需要提前确定这些值,并且在发布游戏后不要更改它们。

关于数据加密

存储的数据不会自动加密。 如果玩家的能力按原样保存,用户将自由重写值,这将影响游戏。

您是否需要加密,如果需要,需要什么级别的强度,以及如何处理加密密钥? 要考虑的事情因游戏而异。

我不会在这里解释加密方法,但是如果你在互联网上查找它,它是一种主要的语言和工具,所以我认为有多种方法。 目前,如果您即使打开文件也不了解存储内容的含义,并且如果篡改数据不佳,您将无法使用保存的数据,我认为会有一些反欺诈效果。