Sử dụng PlayerPrefs để đọc và ghi dữ liệu

Trang Cập Nhật :
Ngày tạo trang :

Môi trường xác minh

Windows
  • cửa sổ 11
Biên tập viên Unity
  • 2021.3.3F1
Gói hệ thống đầu vào
  • 1.3.0

Điều kiện tiên quyết cho mẹo này

Các cài đặt sau đây đã được thực hiện trước làm tiền đề cho mô tả về mẹo này.

Lúc đầu

Nếu bạn đã chơi trò chơi, hầu hết các bạn đã trải nghiệm nó. Có thể bạn đã tạm dừng một trò chơi và lưu hoặc tải dữ liệu chơi của mình để rời đi.

Khi tạo trò chơi, bạn thường cần tạo chức năng lưu và tải này, đặt tùy chọn, v.v. Ở đây, chúng tôi sẽ cố gắng đạt được điều này bằng cách sử dụng cách đơn giản nhất PlayerPrefs để lưu trữ và tải dữ liệu.

Vị trí giao diện người dùng

Ở đây, chúng tôi sẽ cố gắng lưu hoặc đọc nội dung đầu vào bằng cách đặt các mục và nút đầu vào và nhấp vào nút. Hiện tại, bạn chỉ cần ít nhất hai nút và một trường nhập, vì vậy hãy thoải mái đặt chúng.

Chuẩn bị xử lý giao diện người dùng

Đầu tiên, hãy thực hiện nút lưu. Cách tạo sự kiện nút được giới thiệu trong các mẹo sau, vì vậy tôi sẽ chỉ liệt kê các phần có liên quan.

Để tên tập lệnh ButtonEvent là .

Kịch bản trông như thế này:

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()
  {
  }
}

Vì cần phải lấy hoặc đặt giá trị đã nhập, hãy chuẩn bị nó dưới dạng một trường. Ngoài ra, bao gồm phương thức sẽ được gọi khi bạn nhấp vào từng nút.

Đính kèm tập lệnh của bạn EventSystem và đặt từng trường nhập. Nó có thể là bất kỳ đối tượng nào bạn muốn gắn vào.

Đặt từng phương thức sẽ được gọi khi nút được nhấp.

Lưu giá trị

Bây giờ phương thức được gọi khi OnClickSave nhấp vào nút lưu, quá trình của nút lưu như sau.

/// <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 Phương thức được đặt thành khóa và giá trị cần lưu. Khóa được chỉ định khi tải dữ liệu đã lưu. SetString Ở đây chúng ta đang gọi phương thức vì giá trị được lưu trữ là một chuỗi. int float Nếu bạn muốn SetInt lưu một giá trị của một kiểu khác, chẳng hạn như và , có các phương thức như và SetFloat , vì vậy hãy gọi chúng theo kiểu.

PlayerPrefs.Save Cuối cùng, gọi phương thức để xác nhận lưu. Trên thực tế, nó có thể được lưu ngay cả khi bạn không gọi phương thức này, nhưng sẽ an toàn hơn khi gọi nó.

Tuy nhiên, ngay cả khi bạn chạy trò chơi tại thời điểm này, nó sẽ chỉ lưu giá trị, vì vậy bạn sẽ không biết liệu nó đã được lưu đúng cách hay chưa. Nếu bạn kiểm tra vị trí đã lưu, bạn có thể xem dữ liệu, nhưng ...

Nhận giá trị đã lưu

Tiếp theo, thực hiện quá trình tải dữ liệu đã lưu. Việc xử lý nút giống như quá trình lưu, vì vậy chỉ có mã của quá trình tải được mô tả ở đây.

/// <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");
}

Sử dụng phương pháp để PlayerPrefs.GetString tải dữ liệu đã lưu. Bạn có thể lưu giá trị bằng khóa đó bằng cách chỉ định khóa được chỉ định trong Lưu dưới dạng đối số. Giá trị được truy xuất trong giá trị trả về của phương thức.

Điều này cũng được lưu dưới dạng một chuỗi theo cách tương tự như khi lưu, vì vậy GetString chúng tôi gọi phương thức. int float Nếu bạn GetIntGetFloat đang lưu bằng hoặc , hãy gọi phương thức.

Giá trị truy xuất được phản ánh trong trường nhập.

Bây giờ bạn có thể lưu và tải dữ liệu. Tôi không nghĩ có bất kỳ yếu tố khó khăn nào.

Hãy thử di chuyển nó

Chạy để nhập, lưu và tải. Dữ liệu đã lưu được duy trì và có thể được tải ngay cả khi bạn thoát và chạy lại trò chơi. Nếu bạn có thể xác nhận mô hình sau đây, tôi nghĩ không có vấn đề gì.

  1. Nhập giá trị
  2. Nhấp vào nút Lưu
  3. Thay đổi giá trị bạn đã nhập
  4. Nhấp vào nút nhập để xác nhận rằng nó trở về giá trị đã lưu.
  5. Thoát khỏi trò chơi
  6. Chạy lại trò chơi và nhấp vào nút tải để xem bạn có thể nhớ lại giá trị đã lưu hay không
  7. Nhập một giá trị khác, lưu nó và kiểm tra xem bạn có thể đọc tương tự với giá trị được cập nhật hay không

Lưu và tải một đoạn dữ liệu

Trong mẫu cho đến nay, chỉ có một vài thông số đã được lưu. Khi bạn thực sự tạo một trò chơi, số lượng thông số được lưu sẽ tăng đều đặn và nếu bạn đọc và viết từng cái một, mã sẽ rất lớn. Do đó, khi tạo dữ liệu để thực sự được lưu, lý thuyết là kết hợp dữ liệu cần lưu thành một và sau đó ghi tất cả cùng một lúc.

Đầu tiên, tạo một cấu trúc dữ liệu lưu dưới dạng một lớp. Mục tiêu là có thể đọc và ghi dữ liệu cùng một lúc, nhưng cũng để phân loại dữ liệu để giúp mã dễ dàng truy cập vào từng phần dữ liệu.

Sau đây là ví dụ về các lớp trò chơi lưu: Nó có thể được viết bất cứ nơi nào nó có thể được tham chiếu từ mã khác. Cấu trúc lớp này là một mẫu, vì vậy trong một trò chơi thực sự, bạn cần tạo nó cho trò chơi của mình.

/// <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;
}

List Trong hàm chuẩn Unity được sử dụng lần này, nếu bạn xác định mảng hoặc có nhiều lớp duy nhất, System.Serializable Nếu bạn không thêm một thuộc tính, nó sẽ không được chuyển đổi chính xác, vì vậy Character tôi thiết lập thuộc tính cho Serializable lớp.

Sau khi bạn tạo lớp, hãy tạo dữ liệu để lưu. Tất nhiên, bạn có thể có các trường hợp của lớp này trong suốt trò chơi. Điều này phụ thuộc vào cách trò chơi được thực hiện.

// 保存するデータ作成
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, },
  },
};

Sau khi thiết lập JsonUtility.ToJson dữ liệu trong thể hiện của lớp, hãy chuyển đổi (tuần tự hóa) nó thành chuỗi JSON bằng phương thức. Vì giá trị của đối tượng là một "chuỗi" duy nhất được gọi là JSON với cấu trúc dữ liệu, tất cảPlayerPrefs.SetString dữ liệu có thể được ghi bằng một lệnh gọi duy nhất đến phương thức.

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

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

Tuy nhiên, vì tất cả dữ liệu được thu thập trong một, nên không thể chỉ lưu một phần của nó hoặc chỉ đọc một phần của nó. Do đó, tốt hơn là làm cho nó trở thành một đơn vị dễ tóm tắt, chẳng hạn như kết hợp nó thành một đối tượng cho một lưu dữ liệu.

Khi đọc dữ liệu đã lưu, bạn có thể thực hiện xử lý ngược lại khi lưu. Dữ liệu cần đọc là một chuỗi duy nhất, nhưng nội dung là cấu trúc dữ liệu có định dạng JSON, vì vậy JsonUtility.FromJson chúng có thể được chuyển đổi (deserialized) thành các trường hợp lớp bằng các phương thức. Tuy nhiên, vì chúng ta không FromJson có thông tin trong chuỗi lớp nào để chuyển đổi thành, chúng ta phải chỉ định kiểu khi gọi phương thức.

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

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

Nếu bạn cố gắng di chuyển nó, bạn có thể thấy rằng nó được lưu chính xác và có thể được tải.

Nhân tiện, lần này chúng ta đang sử dụng các lớp tiêu chuẩn JsonUtility Unity, nhưng chúng có thể không chuyển đổi được các lớp có cấu trúc dữ liệu phức tạp vì chúng không hoạt động tốt. Trong trường hợp đó, nên sử dụng các thư viện khác.

Dữ liệu được lưu trữ ở đâu?

PlayerPrefs Khi bạn sử dụng một lớp để lưu trữ dữ liệu, vị trí lưu nó phụ thuộc vào nền tảng bạn đang chạy. Vui lòng tham khảo trang chính thức bên dưới để biết nơi nó thực sự được lưu trữ.

Trong một số môi trường, chẳng hạn như Windows, chúng không được lưu trữ trong một tệp, mà trong các cài đặt hệ thống như sổ đăng ký. Vì nó không phải là một tệp, nó không phù hợp để lưu dữ liệu đã lưu trong , ví dụ: nếu dữ liệu lưu rất lớn hoặc PlayerPrefs bạn muốn đồng bộ hóa dữ liệu đã lưu với môi trường khác. Ngược lại, nếu dữ liệu được lưu là kích thước của cấp độ tùy chọn hoặc nếu đó là một trò chơi độc lập chỉ được hoàn thành trong môi trường mà nó đang chạy, tôi nghĩ PlayerPrefs có thể lưu dữ liệu trong .

Ngoài ra, đường dẫn của vị trí đã lưu có thể bị ảnh hưởng bởi cài đặt "Tên công ty" và "Tên sản phẩm". Nếu bạn muốn xuất bản trò chơi của mình, bạn cần quyết định trước các giá trị này và không thay đổi chúng sau khi bạn xuất bản trò chơi của mình.

Giới thiệu về mã hóa dữ liệu

Dữ liệu được lưu trữ không được mã hóa tự động. Nếu khả năng của người chơi được lưu như hiện tại, người dùng sẽ tự do viết lại các giá trị, điều này sẽ ảnh hưởng đến trò chơi.

Bạn có cần mã hóa không và nếu có, mức độ mạnh nào được yêu cầu và cách bạn xử lý khóa mã hóa? Những điều cần xem xét khác nhau giữa các trò chơi.

Tôi sẽ không giải thích phương pháp mã hóa ở đây, nhưng nếu bạn tra cứu nó trên Internet, nó là một ngôn ngữ và công cụ chính, vì vậy tôi nghĩ rằng có nhiều phương pháp khác nhau. Hiện tại, nếu bạn không hiểu ý nghĩa của nội dung được lưu trữ ngay cả khi bạn mở tệp và nếu bạn giả mạo dữ liệu kém, bạn sẽ không thể sử dụng dữ liệu đã lưu, tôi nghĩ rằng sẽ có một số hiệu ứng chống gian lận.