当前位置: 首页 > news >正文

【图文详解】Unity存储游戏数据的几种方法

Unity3D存储游戏数据的方式

  • 1 PlayerPrefs: Unity自带的一种简单的键值存储系统
  • 2 ScriptableObject: Unity中最灵活的数据管理工具
    • 2.1 如何手动创建和修改数据文件
    • 2.2 ScriptableObject优缺点总结
  • 3 JSON: 轻量级的数据交换格式
    • 3.1 序列化与反序列化
    • 3.2 用JsonUtility对对象进行序列化和反序列化
  • 4 XML:一种可扩展标记语言
  • 5 三者特点总结
  • 6 数据库:存储大量数据时使用的一种方法
    • 1.安装SQLite插件
    • 2.创建数据库和表
    • 3.插入和查询数据
  • 结束语

在Unity中,常用的数据存储方法包括PlayerPrefs、ScriptableObject、JSON、XML和数据库等。

PlayerPrefs是Unity自带的一种简单的键值存储系统,适合存储一些简单的游戏数据。ScriptableObject是一种Unity类,可用于创建可序列化的对象并存储数据。JSON和XML是轻量级的数据交换格式,可以通过读写文件的方式进行数据存储和传输。对于存储大量数据,使用数据库则是更好的选择。

1 PlayerPrefs: Unity自带的一种简单的键值存储系统

PlayerPrefs是Unity自带的一种简单的键值(键即用于查找的关键字,值即存储的数据)存储系统,用于存储少量的游戏数据。PlayerPrefs是基于本地文件存储数据的,数据以键值对的形式保存在本地磁盘上。

PlayerPrefs主要适用于一些简单的游戏数据的存储,例如玩家的音效、音乐、难度等级等。使用PlayerPrefs可以方便地在游戏中读写这些数据。

PlayerPrefs的使用非常简单。首先需要使用
PlayerPrefs.SetInt()、
PlayerPrefs.SetFloat()、
PlayerPrefs.SetString()等方法将数据存储在PlayerPrefs中。
例如,用PlayerPrefs.SetInt(“Level”, 5)将当前玩家的游戏等级存储在PlayerPrefs中。然后在需要使用这些数据的地方,使用PlayerPrefs.GetInt()、PlayerPrefs.GetFloat()、PlayerPrefs.GetString()等方法从PlayerPrefs中读取数据。

具体例子就不多讲了,网上有很多介绍。但需要注意的是,PlayerPrefs只适合存储少量数据,如果需要存储大量数据,建议使用其他的数据存储方式,如ScriptableObject、JSON、XML或数据库等。此外,PlayerPrefs存储的数据可以被修改或删除,因此在实际开发中需要注意数据安全性和数据的备份。

2 ScriptableObject: Unity中最灵活的数据管理工具

ScriptableObject是Unity中的一个类,可以用于创建可序列化的对象并存储数据。它们的序列化和反序列化速度更快,消耗的内存更少。与常规的游戏对象不同,ScriptableObject不依赖于场景,也不需要被实例化,因此可以独立于游戏对象存在。

使用ScriptableObject可以方便地创建自定义的数据类,存储一些游戏数据,例如角色属性、游戏设置、关卡数据等。这些数据可以在不同场景之间共享,也可以在不同的游戏对象之间共享。

创建ScriptableObject非常简单。首先,需要在Unity编辑器中创建一个ScriptableObject类,该类需要继承自ScriptableObject,并添加[CreateAssetMenu]属性。然后,需要实现需要存储的数据成员,并将其声明为public或[SerializeField],使其可以被序列化并存储在ScriptableObject中。

下面开始演示:
首先,在Unity编辑器中,创建一个名为MyData的ScriptableObject类:

using UnityEngine;
//关于[CreateAssetMenu]下面有介绍
[CreateAssetMenu(fileName = "NewData", menuName = "MyData", order = 51)]
public class MyData : ScriptableObject
{//public int level;public float health;public string playerName;
}

这里我们定义了一个包含level、health和playerName三个属性的MyData类。属性的类型可以是任何Unity支持的类型,包括int、float、string、Vector3等。

在本例中,我们将数据存储在ScriptableObject对象中,并在控制台中输出这些数据:

public class DataManager : MonoBehaviour
{public MyData data;void Start(){// 将数据存储在ScriptableObject对象中data.level = 10;data.health = 80.0f;data.playerName = "XiaoMing";// 从ScriptableObject对象中读取数据并输出到控制台Debug.Log("Level: " + data.level);Debug.Log("Health: " + data.health);Debug.Log("Player Name: " + data.playerName);}
}

在这段代码中,我们首先在Start()函数中将数据存储在ScriptableObject对象中。然后,通过访问ScriptableObject对象中的属性来读取这些数据,并将其输出到控制台中。

在第一段代码中的[CreateAssetMenu]是一个特性(Attribute),用于在Unity编辑器中为ScriptableObject类创建一个自定义的上下文菜单,方便用户在Project窗口中创建和管理ScriptableObject对象。该特性包含三个参数:

  1. fileName:表示创建的ScriptableObject对象的文件名。在这里,我们使用"NewData"作为文件名。
  2. menuName:表示在Unity编辑器中创建菜单项的路径,以“/”作为分隔符。在这里,我们使用"MyData"作为菜单名,并将其放在根目录下。
  3. order:表示菜单项在上下文菜单中的排序位置。较小的数字表示菜单项靠前。在这里,我们用51作为排序位置。

当我们在Unity编辑器中右键单击Project窗口中的文件夹时,会看到一个名为"MyData"的菜单项。点击它,就可以在该文件夹下创建一个新的ScriptableObject对象,并自动命名为"NewData"。

使用[CreateAssetMenu]特性可以大大简化ScriptableObject对象的创建过程,并使用户更容易使用和管理这些对象。

2.1 如何手动创建和修改数据文件

如果要手动创建和编辑数据文件,那么可以使用AssetDatabase.CreateAsset()方法,它只能在Unity编辑器中使用,不能在游戏运行时使用。使用该方法,开发人员可以方便地创建、修改和管理ScriptableObject对象,提高开发效率并简化资源管理。

这是一个使用AssetDatabase.CreateAsset()方法创建ScriptableObject对象的示例:

using UnityEngine;
using UnityEditor;public class CreateData : MonoBehaviour
{[MenuItem("Tools/Create Data")]static void CreateMyData(){// 创建一个新的MyData对象,MyData是上放刚刚创建的MyData类MyData data = ScriptableObject.CreateInstance<MyData>();// 设置MyData对象的属性data.level = 10;data.health = 80.0f;data.playerName = "Tom";// 在Assets文件夹中创建一个名为"MyData.asset"的新文件,并将MyData对象保存到该文件中AssetDatabase.CreateAsset(data, "Assets/MyData.asset");AssetDatabase.SaveAssets();// 在控制台输出创建的MyData对象的信息Debug.Log("Created MyData asset: " + AssetDatabase.GetAssetPath(data));Debug.Log("Level: " + data.level);Debug.Log("Health: " + data.health);Debug.Log("Player Name: " + data.playerName);// 也可以刷新Asset数据库,这样在编辑器中看到新创建的AssetAssetDatabase.Refresh();}
}

2.2 ScriptableObject优缺点总结

ScriptableObject的优点在于可以方便地创建自定义的数据类,可以在不同的场景或游戏对象之间进行传递、共享数据,还可以使用版本控制工具管理数据的修改。与PlayerPrefs相比,ScriptableObject可以存储大量的游戏数据,且更加灵活和安全。

但是,使用ScriptableObject也有一些限制。例如,由于ScriptableObject不依赖于场景,因此不能直接使用场景中的游戏对象。此外,ScriptableObject存储的数据是以.asset文件的形式保存在本地磁盘上的,因此需要注意数据的安全性和备份。

3 JSON: 轻量级的数据交换格式

3.1 序列化与反序列化

在讲本篇内容之前,首先我们要知道什么是“序列化”和“反序列化”。
序列化是将对象转换为可传输或可存储的格式的过程。序列化可以将一个对象转换为二进制数据流、XML文档或JSON字符串等格式。
反序列化是将序列化的数据转换回对象的过程。反序列化可以将二进制数据流、XML文档或JSON字符串等格式的数据转换回原始的对象,以便在程序中继续使用这些数据。例如,在Unity游戏中,可以从服务器或其他客户端接收JSON格式的字符串,并将其反序列化为游戏数据对象。
序列化与反序列化
JSON和XML是常用的文本格式,它们都支持跨平台传输,并且易于阅读和处理。在Unity中,可以使用XmlSerializer类或JsonUtility类将对象序列化为相应的XML或JSON格式的字符串,然后通过网络传输。

二进制格式可以更有效地传输数据,因为它可以减少数据量和传输时间。在Unity中,可以使用BinaryFormatter类将对象序列化为二进制格式的字节数组,然后通过网络传输。但需要注意的是,二进制格式不太易读和处理,因此在开发和调试阶段,使用文本格式可以更方便。

在实际的开发中,开发人员通常会根据具体的应用场景选择不同的数据传输格式。例如,如果数据需要在Web应用程序之间传输,则JSON格式通常是首选,因为它比XML格式更轻量级。如果数据需要与其他系统进行交互,则XML格式通常是首选,因为它是一种通用的数据交换格式,被广泛使用。
下表总结了JSON、XML和二进制数据的特点和使用场景:

数据格式特性使用场景
JSON轻量级、易读、易解析、支持复杂数据类型、支持嵌套数据结构Web应用程序、移动应用程序、API交互、跨平台应用程序
XML通用的数据交换格式、可扩展性好。支持复杂数据类型、支持嵌套数据结构、支持命名空间数据交换、Web服务、中间件、跨平台应用程序
二进制传输效率高、数据量小、可扩展、支持复杂数据类型、安全性高游戏开发、高性能应用程序、大规模数据处理、机器学习

3.2 用JsonUtility对对象进行序列化和反序列化

在Unity中,可以使用JsonUtility、XMLSerializer、BinaryFormatter等工具对对象进行序列化和反序列化。

下面是一个示例代码,演示如何使用JsonUtility类将一个包含多个属性的对象序列化为JSON格式的字符串,以及如何将JSON格式的字符串反序列化为对象。

using UnityEngine;
using System;// 定义一个包含多个属性的类
[Serializable]
public class PlayerData
{public int level;public string playerName;public float health;
}public class JsonDemo : MonoBehaviour
{void Start(){// 创建一个PlayerData对象并设置属性PlayerData player = new PlayerData();player.level = 10;player.playerName = "XiaoMing";player.health = 100.0f;// 将PlayerData对象序列化为JSON格式的字符串string json = JsonUtility.ToJson(player);// 打印序列化后的JSON字符串Debug.Log("JSON: " + json);// 将JSON字符串反序列化为PlayerData对象PlayerData player2 = JsonUtility.FromJson<PlayerData>(json);// 打印反序列化后的对象的属性Debug.Log("Level: " + player2.level);Debug.Log("Name: " + player2.playerName);Debug.Log("Health: " + player2.health);}
}

在代码中,首先定义了一个包含多个属性的PlayerData类,并使用[Serializable]属性将其标记为可序列化。然后,在Start()方法中,创建了一个PlayerData对象,并将其序列化为JSON格式的字符串,使用JsonUtility.ToJson()方法实现。接着,打印序列化后的JSON字符串。然后,使用JsonUtility.FromJson()方法将JSON格式的字符串反序列化为PlayerData对象,并打印反序列化后的对象的属性

需要注意的是,JsonUtility类只能序列化和反序列化Unity支持的类型,例如int、float、string、Vector3等。如果需要序列化其他类型的对象,需要自己实现序列化和反序列化的逻辑。此外要注意JSON格式的字符串的安全性和数据完整性。

4 XML:一种可扩展标记语言

XML(Extensible Markup Language)是一种可扩展标记语言。在Unity中,可以使用XmlSerializer类将对象序列化为XML格式的字符串,也可以将XML格式的字符串反序列化为对象。

下面是一个示例代码,演示了如何将一个包含多个属性的对象序列化为XML格式的字符串,以及如何将XML格式的字符串反序列化为对象。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;// 定义一个包含多个属性的类
[XmlRoot("PlayerData")]
public class PlayerData
{[XmlElement("Level")]public int level;[XmlElement("PlayerName")]public string playerName;[XmlElement("Health")]public float health;
}public class XmlDemo : MonoBehaviour
{void Start(){// 创建一个PlayerData对象并设置属性PlayerData player = new PlayerData();player.level = 10;player.playerName = "XiaoMing";player.health = 100.0f;// 将PlayerData对象序列化为XML格式的字符串XmlSerializer serializer = new XmlSerializer(typeof(PlayerData));StringWriter writer = new StringWriter();serializer.Serialize(writer, player);string xml = writer.ToString();// 打印序列化后的XML字符串Debug.Log("XML: " + xml);// 将XML字符串反序列化为PlayerData对象StringReader reader = new StringReader(xml);PlayerData player2 = serializer.Deserialize(reader) as PlayerData;// 打印反序列化后的对象的属性Debug.Log("Level: " + player2.level);Debug.Log("Name: " + player2.playerName);Debug.Log("Health: " + player2.health);}
}

在代码中,首先定义了一个包含多个属性的PlayerData类,并使用[XmlRoot]和[XmlElement]属性将其标记为可序列化。然后,在Start()方法中,创建了一个PlayerData对象,并将其序列化为XML格式的字符串,使用XmlSerializer类实现。接着,打印序列化后的XML字符串。然后,使用XmlSerializer.Deserialize()方法将XML格式的字符串反序列化为PlayerData对象,并打印反序列化后的对象的属性。

需要注意的是,XmlSerializer类只能序列化和反序列化具有公共无参数构造函数的对象。此外,需要注意XML格式的字符串的安全性和数据完整性。

5 三者特点总结

CSDN的表不太好做,直接截图吧:
XML、JSON、二进制

这只是一份简单的总结,实际上在选择数据格式时,还需要考虑许多其他因素,如开发成本、可维护性、兼容性等。

6 数据库:存储大量数据时使用的一种方法

数据库一般用于存储大量的结构化数据。在游戏中,我们通常需要存储大量的数据,比如玩家的角色信息、物品信息等,这时候使用数据库就非常合适。本文将介绍如何在Unity中使用SQLite数据库来存储游戏数据。

1.安装SQLite插件

使用SQLite数据库需要安装插件。

2.创建数据库和表

可以使用SQLiteConnection类来连接SQLite数据库:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mono.Data.Sqlite;public class DatabaseManager : MonoBehaviour
{private string connectionString;// Start is called before the first frame updatevoid Start(){connectionString = "URI=file:" + Application.dataPath + "/PlayerData.db";CreateTable();}// 创建表void CreateTable(){using (var conn = new SqliteConnection(connectionString)){conn.Open();using (var cmd = conn.CreateCommand()){cmd.CommandText = "CREATE TABLE IF NOT EXISTS Player (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, level INTEGER)";cmd.ExecuteNonQuery();}}}
}

上述代码中,我们首先定义了一个名为connectionString的字符串变量,用于存储连接字符串。在Start函数中,我们将connectionString设置为数据库文件的路径。

然后,我们在CreateTable函数中创建了一个名为"Player"的表,其中包含三个字段:id、name和level。id字段是主键,使用AUTOINCREMENT关键字表示自动递增。name字段存储角色的名称,level字段存储角色的等级。注意使用IF NOT EXISTS语句来判断表是否已经存在,避免重复创建。

3.插入和查询数据

创建了数据库和表之后,就可以向表中插入数据和查询数据了。以下是一个示例代码,演示如何向"Player"表中插入一条玩家角色信息,并查询所有的角色信息。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mono.Data.Sqlite;public class DatabaseManager : MonoBehaviour
{private string connectionString;// Start is called before the first frame updatevoid Start(){connectionString = "URI=file:" + Application.dataPath + "/PlayerData.db";CreateTable();//创建表InsertData("Jack", 10);//向"Player"表中插入一条玩家角色信息QueryData();//查询所有的角色信息}// 创建表void CreateTable(){using (var conn = new SqliteConnection(connectionString)){conn.Open();using (var cmd = conn.CreateCommand()){cmd.CommandText = "CREATE TABLE IF NOT EXISTS Player (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, level INTEGER)";cmd.ExecuteNonQuery();}}}// 插入数据void InsertData(string name, int level){using (var conn = new SqliteConnection(connectionString)){conn.Open();using (var cmd = conn.CreateCommand()){cmd.CommandText = "INSERT INTO Player (name, level) VALUES (@name, @level)";cmd.Parameters.AddWithValue("@name", name);cmd.Parameters.AddWithValue("@level", level);cmd.ExecuteNonQuery();}}}// 查询数据void QueryData(){using (var conn = new SqliteConnection(connectionString)){conn.Open();using (var cmd = conn.CreateCommand()){cmd.CommandText = "SELECT * FROM Player";using (var reader = cmd.ExecuteReader()){while (reader.Read()){var id = reader.GetInt32(0);var name = reader.GetString(1);var level = reader.GetInt32(2);Debug.LogFormat("id: {0}, name: {1}, level: {2}", id, name, level);}}}}}
}

上述代码中,我们首先在Start函数中调用CreateTable函数来创建表。然后,我们调用InsertData函数来向"Player"表中插入一条玩家角色信息。在InsertData函数中,我们使用INSERT INTO语句来插入数据,使用@name和@level占位符来设置参数的值。

在QueryData函数中,我们使用SELECT语句来查询数据,并使用reader对象来读取查询结果。注意,我们使用GetInt32和GetString方法来读取不同类型的字段值。

这就是使用SQLite数据库在Unity中存储游戏数据的方法,通过这种方法,我们可以轻松地存储大量的结构化数据,方便地进行数据的插入、查询、更新和删除等操作。

结束语

总的来说,在游戏开发中,存储游戏数据是非常重要的,因为游戏数据决定了游戏的各个方面,例如游戏的进度、玩家的成就、游戏的设置等等

不同的方法有不同的特点和应用场景,在实际的游戏开发中,我们可以根据实际的需求选择合适的数据存储方法。如果我们只存储一些简单的数据,可以选择PlayerPrefs;如果存储一些复杂的数据,可以选择JSON或XML;如果需要存储大量的结构化数据,可以选择SQLite数据库。

同的方法有不同的特点和应用场景,我们可以根据具体情况选择合适的方法来存储游戏数据。掌握这些存储数据的技巧将有助于我们更好地开发游戏并提供更好的用户体验。

相关文章:

【图文详解】Unity存储游戏数据的几种方法

Unity3D存储游戏数据的方式1 PlayerPrefs: Unity自带的一种简单的键值存储系统2 ScriptableObject: Unity中最灵活的数据管理工具2.1 如何手动创建和修改数据文件2.2 ScriptableObject优缺点总结3 JSON: 轻量级的数据交换格式3.1 序列化与反序列化3.2 用JsonUtility对对象进行序…...

SESAM 安装教程

SESAM &#xff08;Super Element Structure Analysis Module&#xff09;是由挪威船级社&#xff08;DNV-GL&#xff09;开发的一款有限元分析&#xff08;FEA&#xff09;系统&#xff0c;它以 GeniE、HydroD 和 DeepC 等模块为核心&#xff0c;主要用于海工结构的强度评估、…...

语言文件操作

&#x1f331;博客主页&#xff1a;大寄一场. &#x1f331;系列专栏&#xff1a;C语言学习笔记 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 目录 前言 C语言中的文件打开和关闭 文件指针 文件的打开和关闭 fclose 文件的顺序读写 fseek ftell …...

Java面试题--熔断和降级的区别

熔断和降级都是系统自我保护的一种机制&#xff0c;但二者又有所不同&#xff0c;它们的区别主要体现在以下几点&#xff1a; 概念不同 触发条件不同 归属关系不同 1.概念不同 1.1熔断概念 “熔断”一词早期来自股票市场。熔断&#xff08;Circuit Breaker&#xff09;也…...

阅读笔记5——深度可分离卷积

一、标准卷积 标准卷积在卷积时&#xff0c;同时考虑了特征图的区域和通道信息。 标准卷积的过程如图1-1所示&#xff0c;假设输入特征图的channel3&#xff0c;则每个卷积核的channel都为3&#xff0c;每个卷积核的3个channel对应提取输入特征图的3个channel的特征&#xff08…...

Microsoft Dynamics 365:导入License到服务层,通过Business Central Administration Shell

本文主要是Microsoft Dynamics 365的License导入的图解干货&#xff0c;不多赘述&#xff0c;直接上图&#xff1a;第一步&#xff1a;准备好的License文件放在你喜欢的目录下第二步&#xff1a;到开始程序里找到并打开 Business Central Administration Shell3.第三步&#xf…...

centos6.10安装FastDfs出错的问题

在centos6.10虚拟机安装dfs文件服务器时&#xff0c;安装报错&#xff0c;报错为&#xff1a; gcc: error trying to exec cc1’: execvp: 没有那个文件或目录 1.ping www.baidu.con 排查网络是否通 2.yum update 排查yum源是否可用 3.yum源地址不可用时&#xff0c;修改yu…...

基础组件之内存池

内存池技术 操作系统在运行进程的过程中&#xff0c;会产生内存碎片&#xff0c;降低了内存的使用率。内存池技术就是为了解决/减少内存碎片的一种方法&#xff0c;内部底层的具体实现根据不同业务场景使用不要的方式&#xff0c;以下是一种好理解的方式&#xff0c;供大家一起…...

前端面试题--了解并简单介绍一下typescript

前端面试题–了解并简单介绍一下typescript TypeScript是JavaScript的超集&#xff0c;具有可选的类型并可以编译为纯JavaScript。 从技术上讲TypeScript就是具有静态类型的 JavaScript 。 向JavaScript添加静态类型的原因是什么&#xff1f;我想原因至少有三个&#xff1a; …...

【pytorch】ModuleList 与 ModuleDict

ModuleList 与 ModuleDict1、ModuleList2、ModuleDict3、总结1、ModuleList 1&#xff09;ModuleList 接收一个子模块的列表作为输入&#xff0c;然后也可以类似 List 那样进行 append 和 extend 操作: net nn.ModuleList([nn.Linear(784, 256), nn.ReLU()]) net.append(nn.…...

Hive窗口函数语法规则、窗口聚合函数、窗口表达式、窗口排序函数 - ROW NUMBER 、口排序函数 - NTILE、窗口分析函数

Hive窗口函数 文章目录Hive窗口函数语法规则窗口聚合函数窗口表达式窗口排序函数 - ROW NUMBER窗口排序函数 - NTILE窗口分析函数窗口函数也叫开窗函数、OLAP函数其最大特点&#xff1a;输入值是从SELECT语句的结果集中的一行或多行的“窗口”中获取的。如果函数具有OVER子句&a…...

Go设计模式之函数选项模式

目录引入函数选项模式&#xff08;functional options pattern&#xff09;可选参数默认值接口类型版本引入 假设现在需要定义一个包含多个配置项的结构体&#xff0c;具体定义如下&#xff1a; // DoSomethingOption 定义配置项 type DoSomethingOption struct {// a 配置aa…...

ClickHouse 数据类型、函数大小写敏感性

这里写自定义目录标题SELECT *FROM system.data_type_families注意&#xff1a;case_insensitive0 表示大小写敏感。 ClickHouse 的 String 类型、Int 类型、Float 类型、Decimal类型等都是大小写敏感的&#xff08;case_sensitive0&#xff09;。关于ClickHouse大小写敏感&am…...

nodejs基于vue 网上商城购物系统

可定制框架:ssm/Springboot/vue/python/PHP/小程序/安卓均可开发 目录 1 绪论 1 1.1课题背景 1 1.2课题研究现状 1 1.3初步设计方法与实施方案 2 1.4本文研究内容 2 2 系统开发环境 4 2. 3 系统分析 6 3.1系统可行性分析 6 3.1.1经济可行性 6 3.1.2技术可行性 6 3.1.3运行可行…...

掌握MySQL分库分表(一)数据库性能优化思路、分库分表优缺点

文章目录MySQL数据库性能优化思路【面试题】不分库分表软优化硬优化分库分表结论分库分表能解决的问题解决数据库本身瓶颈连接数解决系统本身IO、CPU瓶颈分库分表带来的问题问题⼀ 跨节点数据库Join关联查询问题二 分库操作带来的分布式事务问题问题三 执行的SQL排序、翻页、函…...

何为小亚细亚?

一、小亚细亚安纳托利亚&#xff08;Anatolia&#xff09;&#xff0c;又名小亚细亚或西亚美尼亚&#xff0c;是亚洲西南部的一个半岛&#xff0c;隶属于土耳其。安纳托利亚半岛&#xff0c;北临黑海&#xff0c;西临爱琴海&#xff0c;南濒地中海&#xff0c;东接亚美尼亚高原…...

【mircopython】ESP32配置与烧录版本

下载ESP32的Micropython固件 官方连接https://www.micropython.org/download/esp32/ 看了下描述&#xff0c;上面的是IDF4.x系列编译&#xff0c;下面是IDF3.x系列编译&#xff0c;我们默认选新的 下载安装CP2102驱动 CP210x USB to UART Bridge VCP Drivers - Silicon Labs…...

Yaml:通过extrac进行传参,关联---接口关联封装(基于一个独立YAML的文件)

一&#xff1a;在common包中&#xff0c;封装一个yaml_util的工具包 1. 将获取到的数据&#xff0c;写入到extrac.yaml文件中&#xff0c;通过data def write_extract_yaml(data): 2. 需要用到该参数时&#xff0c;读取extrac.yaml文件中&#xff0c;由于会有多个参数&#x…...

vue - vue中对Vant日历组件(calendar)的二次封装

vue中对vant日历选择器组件实现的的二次封装&#xff1b;主要实现功能如下: 主要功能&#xff1a; 日期区间选择&#xff08;基本&#xff09;&#xff1b;自定义选择器的底部按钮&#xff0c;添加清除时间操作&#xff08;slot插槽&#xff09;&#xff1b;指定默认选中的日期…...

详解C++的类型转换

文章目录前言一、C语言中的类型转换二、为什么C需要四种转换三、C强制类型转换3.1 static_cast3.2 reinterpret_cast3.3 const_cast3.4 dynamic_cast四、RTTI总结前言 在C语言的类型转换有一个非常大的坑,有好多悄悄地转换,有时候把我们转换的就蒙了,因为C要兼容C语言,所以C就…...

qt network 整体框架

以下是 Qt 网络模块中 QNetworkInterface、TCP、UDP 及相关类的层次关系图及说明&#xff1a; 一、Qt 网络模块层次结构 ┌─────────────────────────────────────────────────────────────┐ │ QtNetwork 模…...

Linux下如何查看一个端口被什么进程占用? 该进程又打开了哪些文件?

Linux下如何查看一个端口被什么进程占用&#xff1f; 该进程又打开了哪些文件&#xff1f; 查看端口 1.使用lsof命令查看端口占用的进程 lsof可以列出系统上打开的文件&#xff0c;其中包括网络连接、进程信息等。 lsof -i:<端口号> 例如&#xff0c;如果需…...

分析 java 的 Map<String,Map<String, List<Map<String,Integer>>>>

import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;public class Test02 {public static void main(String[] args) {//分析方法&#xff1a;由外层向内层逐渐拆解要定义的变量。再由内向外进行变量赋值//外层第一层&#x…...

机器翻译模型笔记

机器翻译学习笔记&#xff08;简体中文&#xff09; 1. 任务概述 目标&#xff1a;将英文句子翻译成简体中文。 示例&#xff1a; 输入&#xff1a;Tom is a student. 输出&#xff1a;汤姆是一个学生。 框架&#xff1a;Seq2Seq&#xff08;序列到序列&#xff09;模型。…...

预览pdf(url格式和blob格式)

<template><div class"pdf-container"><div v-if"loading" class"loading-state"><a-spin size"large" /></div><div v-else-if"error" class"loading-state">加载失败&…...

在命令行直接执行可以执行成功,加入crontab定时任务执行shell脚本不成功失败的问题解决方法

今天遇到在命令行直接执行可以执行成功&#xff0c;加入crontab定时任务执行shell脚本却不成功失败的问题&#xff0c;踩坑了很长时间 记录下我的解决方法 原来我的定时任务填写方式: [roottao ~]# crontab -l */10 * * * * /bin/sh /search/index.sh >>/dev/null 2&g…...

理解 RAG_HYBRID_BM25_WEIGHT:打造更智能的混合检索增强生成系统

目录 理解 RAG_HYBRID_BM25_WEIGHT&#xff1a;打造更智能的混合检索增强生成系统 一、什么是 Hybrid RAG&#xff1f; 二、什么是 RAG_HYBRID_BM25_WEIGHT&#xff1f; 三、参数设置示例 四、什么时候该调整它&#xff1f; 五、实战建议 六、总结 理解 RAG_HYBRID_BM25…...

SQL进阶之旅 Day 18:数据分区与查询性能

【SQL进阶之旅 Day 18】数据分区与查询性能 文章简述 在现代数据库系统中&#xff0c;随着数据量的快速增长&#xff0c;如何高效地管理和查询大规模数据成为开发人员和数据分析师面临的重要挑战。本文深入探讨了数据分区的概念及其对查询性能的提升作用&#xff0c;结合理论…...

计算机组成与体系结构:补码数制二(Complementary Number Systems)

目录 4位二进制的减法 补码系统 &#x1f9e0;减基补码 名字解释&#xff1a; 减基补码有什么用&#xff1f; 计算方法 ❓为什么这样就能计算减基补码 &#x1f4a1; 原理揭示&#xff1a;按位减法&#xff0c;模拟总减法&#xff01; 那对于二进制呢&#xff1f;&…...

双碳时代,能源调度的难题正从“发电侧”转向“企业侧”

安科瑞刘鸿鹏 摘要 在“双碳”战略和能源结构转型的大背景下&#xff0c;企业储能电站逐步成为提升能源利用效率、增强用能韧性的重要手段。随着系统规模扩大与运行复杂度提升&#xff0c;如何对光伏、储能、负荷等流进行实时调控&#xff0c;成为智慧用能的关键。ACCU100微…...