[Diario de aprendizaje de Unity 03] Persistencia de datos

Solo se puede decir que este artículo ha escrito una parte y no explica completamente el funcionamiento de la persistencia de datos en Unity. En el futuro, puede ser un patrón para recordar lo que aprende.

1 concepto

La persistencia de datos es un término colectivo para convertir el modelo de datos en la memoria en un modelo de almacenamiento y convertir el modelo de almacenamiento en un modelo de datos en la memoria.

Versión humana: almacene los datos del juego en el disco duro y lea los datos del disco duro en el juego, lo cual es un guardado en el sentido tradicional.

Flujo de datos variables

2 preferencias de jugador

2.1 Concepto

PlayerPrefs es una clase pública proporcionada por Unity que se puede utilizar para almacenar y leer datos del jugador.

2.2 Operación

1 almacenamiento

El almacenamiento de datos de PlayerPrefs es similar a los pares clave-valor, con una clave correspondiente a un valor. Proporciona 3 métodos de almacenamiento de datos: int, float, string.

Clave: cadena.
Valor: int, float, string, correspondiente a 3 API.

PlayerPrefs.SetInt("Age", 18);
PlayerPrefs.SetFloat("Height", 100);
PlayerPrefs.SetString("Name", ",manqi");

Cabe señalar que llamar directamente a la API solo almacenará los datos en la memoria. Cuando finalice el juego, los datos se guardarán automáticamente en el disco duro.

Si el juego finaliza de forma anormal (caída, etc.), los datos no se guardarán en el disco duro. Para almacenar los datos en el disco duro inmediatamente para evitar pérdidas, podemos usar PlayerPrefs.Save().

PlayerPrefs.Save();  //将数据立刻存储到硬盘中

Sin embargo, podemos ver que PlayerPrefs tiene limitaciones, solo puede almacenar 3 tipos de datos, si hay otros tipos de datos, la precisión solo se puede reducir o se puede cambiar el tipo (por ejemplo, bool true se almacena como int 1 ).

Además, cabe señalar que si se almacena el mismo nombre de clave, los datos originales se sobrescribirán independientemente de si cambia el tipo de datos. (Por lo tanto, debemos garantizar la unicidad de la clave.

PlayerPrefs.SetInt("Age",18);
PlayerPrefs.SetString("Age","18");

2 leer

Utilice int como ejemplo:

//如果没有对应键,会传出默认值,如int-0。
int age = PlayerPrefs.GetInt("Age");
//如果找不到对应键,会传出函数第二个参数。
int age = PlayerPrefs.GetInt("Age",100);

Determine si los datos existen:

if(PlayerPrefs.HasKey("Age")){
    
    
	print("存在");
}

3 Eliminar

//删除指定键值对
PlayerPrefs.DeleteKey("Age");
PlayerPrefs.DeleteAll();

2.3 Ubicación de almacenamiento de Windows

PlayerPrefs se almacenan en el registro bajo la clave HKEY_CURRENT_USER\Software[nombre de la empresa][nombre del producto]. (El nombre de la empresa y el nombre del producto son los nombres establecidos en "Archivo->Configuración de compilación->Configuración del proyecto->Reproductor".

Unidad

Registro
Pero encontraremos que cuando modificamos directamente la información de los datos en el registro, los datos leídos en el juego también cambiarán en consecuencia, lo que constituye un defecto en el uso de PlayerPrefs para almacenar información. Para solucionar este fallo, podemos cifrar o utilizar otros métodos de almacenamiento de datos.

2.4 Análisis de ventajas y desventajas

Ventajas: Sencillo, fácil de entender y fácil de operar.
Desventajas: ① Los tipos de datos que se pueden almacenar directamente son limitados y usted mismo debe implementar tipos complejos de almacenamiento; ② La seguridad de los datos es baja y fácil de modificar.
Ámbito de aplicación: Adecuado para almacenar datos temporales, como las preferencias del jugador.

2.5 Almacenamiento de clases personalizadas

Podemos usar SetString API y JsonUtility de PlayerPrefs para almacenar clases personalizadas.

Clase de método

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class SaveSystem{
    
    
    public static void SaveByPlayerPrefs(string key,object data) {
    
    
        var json = JsonUtility.ToJson(data);
        PlayerPrefs.SetString(key, json);
        PlayerPrefs.Save();
    }
    public static string LoadFromPlayerPrefs(string key) {
    
    
        return PlayerPrefs.GetString(key, null) ;
    }
}

clase de llamada

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {
    
    
    //增加可序列化特性才能被JsonUtility转换
    [System.Serializable]
    class SaveData {
    
    
        public string playerName;
        public string playerLevel;
        public string playerCoin;
        public Vector3 playerPosition;
    }
    const string PLAYER_DATA_KEY = "PlayerData";
    public string playerName;
    public string playerLevel;
    public string playerCoin;
    public Vector3 playerPosition;

    //存档
    SaveData SavingData() {
    
    
        var savaData = new SaveData();
        savaData.playerName = playerName;
        savaData.playerLevel = playerLevel;
        savaData.playerCoin = playerCoin;
        savaData.playerPosition = playerPosition;
        return savaData;
    }
    void SaveByPlayerPrefs() {
    
    
        SaveSystem.SaveByPlayerPrefs(PLAYER_DATA_KEY, SavingData());
    }
    //读档
    void LoadFromPlayerPrefs() {
    
    
        var json = SaveSystem.LoadFromPlayerPrefs(PLAYER_DATA_KEY);
        var saveData = JsonUtility.FromJson<SaveData>(json);
    }
    void LoadData(SaveData saveData) {
    
    
        playerName = saveData.playerName;
        playerLevel = saveData.playerLevel;
        playerName = saveData.playerName;
        playerPosition = saveData.playerPosition;
    }
    //删除
    void DeletePlayerDataPrefs() {
    
    
        PlayerPrefs.DeleteKey(PLAYER_DATA_KEY);
    }
}

3JSON

3.1 Concepto

En Unity, JSON (notación de objetos JavaScript) es un formato de intercambio de datos común. Unity tiene una clase JsonUtility incorporada que se puede usar para serializar objetos en cadenas JSON o deserializar cadenas JSON en objetos.

json

3.2 Utilidad Json

JsonUtility es una clase utilizada en Unity para procesar datos Json. API relacionada: JsonUtility
Convertir

1 JsonUtility.ToJson

El primer parámetro debe admitir la serialización de Unity. Consulte [3.3] para obtener detalles sobre si se puede serializar.
El segundo parámetro se refiere a si se debe convertir a un formato de texto Json que sea más adecuado para la lectura.

var json = JsonUtility.ToJson(object);
var json = JsonUtility.ToJson(object,bool);

Además, cabe señalar que si los datos están vacíos:

bool data;
print(JsonUtility.ToJson(data));

En este momento, la consola solo imprimirá un {}, porque el objeto serializado por Json son los datos en sí, y los datos en sí no almacenan ningún dato. En este momento, Json intentará serializar, pero encontrará que el contenido serializado está vacío, por lo que solo se imprimirá un {}.

Si queremos que Json convierta los campos correctamente, podemos convertir directamente la clase encapsulada.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ToJsonTest : MonoBehaviour{
    
    
    [System.Serializable] class Player {
    
    
        public string playerName;
        public bool isDie;
        public int health;
    }
    void Start(){
    
    
        Player player = new Player();
        print(JsonUtility.ToJson(player));   
    }
}

tojson

2 JsonUtility.FromJson

public static T FromJson(string json);

3 JsonUtility.FromJsonOverwrite

Los datos convertidos sobrescriben el objeto pasado como segundo parámetro.

public static void FromJsonOverwrite(string json,object objectToOverwrite);

3.3 Admite/no admite la serialización de Unity

Una forma sencilla de determinar si Unity puede serializarlo:
marque el tipo como público o marque el atributo [SerializeField] al frente para ver si el tipo se puede mostrar en la ventana del Inspector.
PD: la clase JsonUtility solo admite la serialización y deserialización de objetos C #, y no admite la serialización y deserialización de componentes y objetos de Unity.

concreto:

1 campo

Imagen 3

Categoría 2

Imagen 2
Foto 1

3.4 Sistema de archivo simple basado en Json

Clase de método

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;

public static class SaveSystem{
    
    
    public static void SaveByJson(string saveFileName,object data) {
    
    
        var json = JsonUtility.ToJson(data);
        //Application.persistentDataPath:Unity提供的一个存储永久数据的路径:不同平台上路径不同。
        //Path.Combine:合并传入的路径。
        var path = Path.Combine(Application.persistentDataPath, saveFileName) ;
        //File.WriteAllText方法用于写入字符串类型的数据,而Json是字符串类型。
        File.WriteAllText(path, json);
    }
    public static T LoadFromJson<T>(string saveFileName) {
    
    
        var path = Path.Combine(Application.persistentDataPath, saveFileName);
        var json = File.ReadAllText(path);
        var data = JsonUtility.FromJson<T>(json);
        return data;
    }
    public static void DeleteSaveFile(string saveFileName) {
    
    
        var path = Path.Combine(Application.persistentDataPath, saveFileName);
        File.Delete(path);
    }
}

clase de llamada

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class Test : MonoBehaviour{
    
    
    //增加可序列化特性才能被JsonUtility转换
    [System.Serializable]class SaveData {
    
    
        public string playerName;
        public string playerLevel;
        public string playerCoin;
        public Vector3 playerPosition;
    }
    const string PLAYER_DATA_KEY = "PlayerData";
    const string PLAYER_DATA_FILE_NAME = "PlayerData";
    public string playerName;
    public string playerLevel;
    public string playerCoin;
    
    //存档
    SaveData SavingData() {
    
    
        var saveData = new SaveData();
        saveData.playerName = playerName;
        saveData.playerLevel = playerLevel;
        saveData.playerCoin = playerCoin;
        saveData.playerPosition = transform.position;
        return saveData;
    }
    void SaveByJson() {
    
    
        SaveSystem.SaveByJson(PLAYER_DATA_FILE_NAME, SavingData());
    }
    //读档
    void LoadFromJson() {
    
    
        var saveData = SaveSystem.LoadFromJson<SaveData>(PLAYER_DATA_FILE_NAME);
        LoadData(saveData);
    }
    void LoadData(SaveData saveData) {
    
    
        playerName = saveData.playerName;
        playerLevel = saveData.playerLevel;
        playerCoin = saveData.playerCoin;
        transform.position = saveData.playerPosition;
    }
    //删除
    void DeletePlayerDataFiles() {
    
    
        SaveSystem.DeleteSaveFile(PLAYER_DATA_FILE_NAME);
    }
}

3.6 Análisis de ventajas y desventajas

Ventajas: ① Más acorde con los hábitos de lectura humanos; ② Ampliamente utilizado y adecuado para múltiples lenguajes de programación; ③ Ligero, fácil para transmisión de red y análisis y generación de máquinas.
Desventajas: ① Se admiten tipos de datos limitados (debido a que se implementa a través del serializador de Unity; ② La seguridad de los datos es baja.
Ámbito de aplicación:
Redes: ① Excelente soporte de intercambio de datos en red; ② Archivo en la nube.
Almacenamiento local: ① No confidencial y datos que requieren una gran cantidad de lectura y modificación, como Mod; ② Preferencias del jugador.

4 XML

4.1 Concepto

En Unity, XML (lenguaje de marcado extensible) es un formato de intercambio de datos común. Unity proporciona una biblioteca de clases en el espacio de nombres System.Xml, que se puede utilizar para serializar datos XML en objetos o deserializar objetos en datos XML.

<?xml version="1.0" encoding="UTF-8"?>
<student>
  <student1 name="椎名">
    <age>5</age>
    <sex>man</sex>
  </student1>
  <student2 name="mikan">
    <age>10</age>
    <sex>woman</sex>
  </student2>
  <student3 name="みかん">
    <age>15</age>
    <sex>woman</sex>
  </student3>
</student>

4.2 Sistema de archivo simple basado en XML

Tenga en cuenta que, dado que Unity no admite el uso de la clase XmlSerializer de forma predeterminada, debemos crear una carpeta XML vacía en la carpeta Assets y copiar el archivo MonoXml.dll de la carpeta Windows .NET Framework a la carpeta.

Clase de método

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Xml.Serialization; 

public static class SaveSystem {
    
    
    //存储
    public static void SaveByXml(string saveFileName, object data) {
    
    
        //创建XmlSerializer对象,传入待序列化数据的类型。
        var serializer = new XmlSerializer(data.GetType());
        //创建FileStream对象,指定文件路径和操作模式。
        string path = Path.Combine(Application.persistentDataPath, saveFileName);
        var stream = new FileStream(path, FileMode.Create);
        //序列化数据,并写入文件
        serializer.Serialize(stream, data); 
        stream.Close();
    }

    //读取
    public static T LoadFromXml<T>(string saveFileName) {
    
    
        //创建XmlSerializer对象,传入待反序列化数据的类型
        var serializer = new XmlSerializer(typeof(T));
        //创建FileStream对象,指定文件路径和操作模式。
        string path = Path.Combine(Application.persistentDataPath, saveFileName);
        var stream = new FileStream(path, FileMode.Create);
        //从文件中反序列化数据,并转换为指定类型
        var data = (T)serializer.Deserialize(stream); 
        stream.Close(); 
        return data; 
    }

    //删除
    public static void DeleteSaveFile(string saveFileName) {
    
    
        var path = Path.Combine(Application.persistentDataPath, saveFileName);
        File.Delete(path);
    }
}

clase de llamada

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {
    
    
    //增加可序列化特性才能被转换
    [System.Serializable]
    class SaveData {
    
    
        public string playerName;
        public string playerLevel;
        public string playerCoin;
        public Vector3 playerPosition;
    }
    public string playerName;
    public string playerLevel;
    public string playerCoin;
    public Vector3 playerPosition;
    const string PLAYER_DATA_FILE_NAME = "PlayerData";

    SaveData SavingData() {
    
    
        var savaData = new SaveData();
        savaData.playerName = playerName;
        savaData.playerLevel = playerLevel;
        savaData.playerCoin = playerCoin;
        savaData.playerPosition = playerPosition;
        return savaData;
    }
    //存档
    void SaveByXML() {
    
    
        SaveSystem.SaveByXml(PLAYER_DATA_FILE_NAME,SavingData());
    }
    //读档
    void LoadFromJson() {
    
    
        var saveData = SaveSystem.LoadFromXml<SaveData>(PLAYER_DATA_FILE_NAME);
        LoadData(saveData);
    }
    void LoadData(SaveData saveData) {
    
    
        playerName = saveData.playerName;
        playerLevel = saveData.playerLevel;
        playerCoin = saveData.playerCoin;
        transform.position = saveData.playerPosition;
    }
    //删除
    void DeletePlayerDataFiles() {
    
    
        SaveSystem.DeleteSaveFile(PLAYER_DATA_FILE_NAME);
    }

}

Supongo que te gusta

Origin blog.csdn.net/manpi/article/details/130004813
Recomendado
Clasificación