【Unity数据交互】二进制私

在这里插入图片描述


👨‍💻个人主页:@元宇宙-秩沅

👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!

👨‍💻 本文由 秩沅 原创

👨‍💻 专栏交流🧧
🟥Unity100个实战基础✨🎁
🟦 Unity100个精华一记✨🎁
🟩 Unity50个demo案例教程✨🎁
🟨 Unity100个精华细节BUG✨🎁

在这里插入图片描述

在这里插入图片描述


文章目录

    • 前言
    • 🎶(==1==) 数据相互转换
    • 🎶(==2==) 文件操作
    • 🎶(==3==) 文件夹操作
    • 🎶(==4==) 序列化
    • 🎶(==5==) 反序列化
    • 🎶(==6==)二进制加密
    • 🎶(==7==)Unity中使用Ecxel
      • Excel的使用基础
      • Excel的实践
      • ExcelTool(读取Excel数据生成数据结构、容器、二进制文件)
    • 🎶(==8==) BinaryData管理器
    • 🅰️系统路线学习点击跳转


前言

有符号 sbyte int short long
无符号 byte uint ushort ulong
浮点 float double decimal
特殊 bool char string

变量的本质是2进制,内存中以字节的形式存储,sizeof方法可以看到常用变量类型占用的字节空间长度

sizeof(sbyte)
sizeof(long) …

  • 节约存储空间,提升效率
  • 提升安全性

🎶(1 数据相互转换


  • 在Unity中各类型数据和字节数据相互转换

  • 1.将各类型转字节

byte[] bytes = BitConverter.GetBytes(256);
  • 2.字节数组转各类型
int i = BitConverter.ToInt32(bytes, 0);

为保证编码的正确性,编码要规范化、标准化,即需有标准的编码格式。

在C#中有一个专门的编码格式类 来帮助我们将字符串和字节数组进行转换

游戏开发中常用编码格式 UTF-8
中文相关编码格式 GBK
英文相关编码格式 ASCII

  • 1.将字符串以指定编码格式转字节
byte[] bytes = Encoding.UTF8.GetBytes("你好");
  • 2.字节数组以指定编码格式转字符串
string str = Encoding.UTF8.GetString(bytes);

🎶(2 文件操作


命名空间: System.IO

  • 1.判断文件是否存在
     if(File.Exists(Application.dataPath + "/Text")){//存在}
  • 2.创建文件
FileStream fstream = File.Create(Application.dataPath + "/text");
  • 3.写入文件
     //字节数组 写入到指定路径的文件中byte[] bytes = BitConverter.GetBytes(100);File.WriteAllBytes(Application.dataPath + "/text", bytes);//string数组内容 一行行写入到指定路径中
string[] strs = new string[] { "姓名", "你好", "1", "23"};
File.WriteAllLines(Application.dataPath + "/text", strs);//字符串写入指定路径
File.WriteAllText(Application.dataPath + "/text", "xahhll");
  • 4.读取文件
        //读取字节数据bytes = File.ReadAllBytes(Application.dataPath + "/text");print(BitConverter.ToInt32(bytes, 0));//读取所有行信息
strs = File.ReadAllLines(Application.dataPath + "/text");for (int i = 0; i < strs.Length; i++){print(strs[i]);}//读取所有文本信息
print(File.ReadAllText(Application.dataPath + "/text"));
  • 5.删除文件
  File.Delete(Application.dataPath + "/text");//文件前提是关闭的
  • 6.复制文件
参数一:现有文件 需要是流关闭状态
参数二:目标文件File.Copy(Application.dataPath + "/text", Application.dataPath + "/text2", true);
  • 7.文件替换
        //参数一:用来替换的路径//参数二:被替换的路径//参数三:备份路径File.Replace(Application.dataPath + "/text", Application.dataPath + "/text2", Application.dataPath + "/备份text");
  • 8.以流的形式 打开文件并写入或读取

//参数一:路径
//参数二:打开模式
//参数三:访问模式
FileStream fs = File.Open(Application.dataPath + "/text", 
FileMode.OpenOrCreate, FileAccess.ReadWrite);

🎶(3 文件夹操作


命名空间:using System.IO
作用:增删查改文件夹

  • 1.判断文件夹是否存在
if( Directory.Exists(Application.dataPath + "/文件夹名"))
{print("存在");
}
  • 2.创建文件夹
DirectoryInfo info = Directory.CreateDirectory(Application.dataPath + "/文件夹名");
  • 3.删除文件夹
//参数一:路径
//参数二:true,将删除整个目录,false,仅当该目录为空时才删除
Directory.Delete(Application.dataPath + "/文件夹名");
  • 4.查找文件夹和文件
//得到所有文件夹名
string[] strs = Directory.GetDirectories(Application.dataPath);
for (int i = 0; i < strs.Length; i++)
{print(strs[i]);
}
//得到所有文件名
strs = Directory.GetFiles(Application.dataPath);
for (int i = 0; i < strs.Length; i++)
{print(strs[i]);
}
  • 5.移动文件夹
//移动会把文件夹中的所有内容一起移到新的路径
Directory.Move(Application.dataPath + "/文件夹名", Application.dataPath + "/路径");//该路径下面需为空
  • 6.创建文件夹方法的返回值
DirectoryInfo Info = Directory.CreateDirectory(Application.dataPath + "/文件夹名");
//全路径
print(Info .FullName);
//文件名
print(Info .Name);
  • 7.查找上级文件夹信息
Info = Directory.GetParent(Application.dataPath + "/文件夹名");
//全路径
print(Info .FullName);
//文件名
print(Info .Name);
  • 8.得到所有子文件夹的目录信息
DirectoryInfo[] dInfos = Info.GetDirectories();
FileInfo[] fInfos = dInfo.GetFiles();
for (int i = 0; i < fInfos.Length; i++)
{print("**************");print(fInfos[i].Name);//文件名print(fInfos[i].FullName);//路径print(fInfos[i].Length);//字节长度print(fInfos[i].Extension);//后缀名
}

🎶(4 序列化


序列化类对象

  • 1.第一步申明类对象

注意:如果要使用C#自带的序列化2进制方法
申明类时需要添加[System.Serializable]特性

[System.Serializable]
public class Person
{public int age = 1;public string name = "唐老狮";public int[] ints = new int[] { 1, 2, 3, 4, 5 };public List<int> list = new List<int>() { 1, 2, 3, 4 };public Dictionary<int, string> dic = new Dictionary<int, string>() { { 1,"123"},{ 2,"1223"},{ 3,"435345" } };public StructTest st = new StructTest(2, "123");//结构体public ClssTest ct = new ClssTest();//类
}
  • 第二步—将对象进行2进制序列化

方法一:使用内存流得到2进制字节数组
主要用于得到字节数组 可以用于网络传输
1.内存流对象
类名:MemoryStream
命名空间:System.IO
2.2进制格式化对象
类名:BinaryFormatter
命名空间:System.Runtime.Serialization.Formatters.Binary、

  Person p = new Person();        //主要方法:序列化方法 Serializeusing (MemoryStream ms = new MemoryStream()){//2进制格式化程序BinaryFormatter bf = new BinaryFormatter();//序列化对象 生成2进制字节数组 写入到内存流当中bf.Serialize(ms, p);//得到对象的2进制字节数组byte[] bytes = ms.GetBuffer();//存储字节File.WriteAllBytes(Application.dataPath + "/文件", bytes);//关闭内存流ms.Close();}

方法二:使用文件流进行存储
主要用于存储到文件中

  Person p = new Person();       using (FileStream fs = new FileStream(Application.dataPath + "/文件名", FileMode.OpenOrCreate, FileAccess.Write)){//2进制格式化程序BinaryFormatter bf = new BinaryFormatter();//序列化对象 生成2进制字节数组 写入到内存流当中bf.Serialize(fs, p);fs.Flush();fs.Close();}}
}

🎶(5 反序列化


  • 1.反序列化文件中数据

主要类
FileStream文件流类
BinaryFormatter 2进制格式化类
主要方法
Deserizlize
通过文件流打开指定的2进制数据文件

     using (FileStream fs = File.Open(Application.dataPath + "/文件名", FileMode.Open, FileAccess.Read)){//申明一个 2进制格式化类BinaryFormatter bf = new BinaryFormatter();//反序列化Person p = bf.Deserialize(fs) as Person;fs.Close();}
  • 2.反序列化网络传输过来的2进制数据

主要类
MemoryStream内存流类
BinaryFormatter 2进制格式化类
主要方法
Deserizlize
目前没有网络传输 我们还是直接从文件中获取

  byte[] bytes = File.ReadAllBytes(Application.dataPath + "/文件名");//申明内存流对象 一开始就把字节数组传输进去using (MemoryStream ms = new MemoryStream(bytes)){//申明一个 2进制格式化类BinaryFormatter bf = new BinaryFormatter();//反序列化Person p = bf.Deserialize(ms) as Person;ms.Close();}

🎶(6二进制加密


  • 1,何时加密?何时解密?

当我们将类对象转换为2进制数据时进行加密
当我们将2进制数据转换为类对象时进行解密

  • 2.常用加密算法

MD5算法
SHA1算法
HMAC算法
AES/DES/3DES算法
等等等,ye 有很多的别人写好的第三发加密算法库
可以直接获取用于在程序中对数据进行加密

  • 3.简单的异或加密和解密
       Person p = new Person();byte key = 199;using (MemoryStream ms = new MemoryStream()){BinaryFormatter bf = new BinaryFormatter();bf.Serialize(ms, p);byte[] bytes = ms.GetBuffer();//异或加密for (int i = 0; i < bytes.Length; i++){bytes[i] ^= key;}File.WriteAllBytes(Application.dataPath + "/文件夹名", bytes);}//解密byte[] bytes2 = File.ReadAllBytes(Application.dataPath + "/文件夹名");for (int i = 0; i < bytes2.Length; i++){bytes2[i] ^= key;}using (MemoryStream ms = new MemoryStream(bytes2)){BinaryFormatter bf = new BinaryFormatter();Person p2 = bf.Deserialize(ms) as Person;ms.Close();}

🎶(7Unity中使用Ecxel


  • 导入官方提供的Excel相关DLL文件,在Editor文件夹下
    在这里插入图片描述

Excel的使用基础

  • 1.打开Excel表

主要知识点:
1.FileStream读取文件流
2.IExcelDataReader类,从流中读取Excel数据
3.DataSet 数据集合类 将Excel数据转存进其中方便读取

 [MenuItem("GameTool/打开Excel表")]private static void OpenExcel(){using (FileStream fs = File.Open(Application.dataPath + "/文件夹/Excel表明.xlsx", FileMode.Open, FileAccess.Read )){//通过我们的文件流获取Excel数据IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fs);//将excel表中的数据转换为DataSet数据类型 方便我们 获取其中的内容DataSet result = excelReader.AsDataSet();//得到Excel文件中的所有表信息for (int i = 0; i < result.Tables.Count; i++){Debug.Log("表名:" + result.Tables[i].TableName);Debug.Log("行数:" + result.Tables[i].Rows.Count);Debug.Log("列数:" + result.Tables[i].Columns.Count);}fs.Close();}}
  • 2.获取Excel表中单元格的信息

主要知识点:
1.FileStream读取文件流
2.IExcelDataReader类,从流中读取Excel数据
3.DataSet 数据集合类 将Excel数据转存进其中方便读取
4.DataTable 数据表类 表示Excel文件中的一个表
5.DataRow 数据行类 表示某张表中的一行数据

[MenuItem("GameTool/读取Excel里的具体信息")]private static void ReadExcel(){using (FileStream fs = File.Open(Application.dataPath + "/文件夹/Excel表明.xlsx", FileMode.Open, FileAccess.Read)){IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fs);DataSet result = excelReader.AsDataSet();for (int i = 0; i < result.Tables.Count; i++){//得到其中一张表的具体数据DataTable table = result.Tables[i];//得到其中一行的数据//DataRow row = table.Rows[0];//得到行中某一列的信息//Debug.Log(row[1].ToString());DataRow row;for (int j = 0; j < table.Rows.Count; j++){//得到每一行的信息row = table.Rows[j];Debug.Log("*********新的一行************");for (int k = 0; k < table.Columns.Count; k++){Debug.Log(row[k].ToString());}}}fs.Close();}}
  • 3.获取Excel表中信息对于我们的意义?

我们可以根据表中数据来动态的生成相关数据
1.数据结构类
2.容器类
3.2进制数据

为什么不直接读取Excel表而要把它转成2进制数据
1.提升读取效率
2.提升数据安全性

Excel的实践

  • 1.自定义Excel表的规则
    第一行:字段
    第二行:数据类型
    第三行:主键
    第四行:注释
    之后:数据
    (可用字典的形式存储<key,数据容器>)
    在这里插入图片描述
  • 我们想通过Ecxel表中的内容生成数据结构,生成容器脚本,如何实现呢
    见下文

ExcelTool(读取Excel数据生成数据结构、容器、二进制文件)

导入包
在这里插入图片描述

  • 在Assets文件夹下创建 ArtRes/Excel,然后放入编辑好的Excel文件
    在这里插入图片描述

  • 然后点击上方GenerateEXcel,即可生成
    在这里插入图片描述

在这里插入图片描述

using Excel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;public class ExcelTool
{/// <summary>/// excel文件存放的路径/// </summary>public static string EXCEL_PATH = Application.dataPath + "/ArtRes/Excel/";/// <summary>/// 数据结构类脚本存储位置路径/// </summary>public static string DATA_CLASS_PATH = Application.dataPath + "/Scripts/ExcelData/DataClass/";/// <summary>/// 容器类脚本存储位置路径/// </summary>public static string DATA_CONTAINER_PATH = Application.dataPath + "/Scripts/ExcelData/Container/";/// <summary>/// 真正内容开始的行号/// </summary>public static int BEGIN_INDEX = 4;[MenuItem("GameTool/GenerateExcel")]private static void GenerateExcelInfo(){//记在指定路径中的所有Excel文件 用于生成对应的3个文件DirectoryInfo dInfo = Directory.CreateDirectory(EXCEL_PATH);//得到指定路径中的所有文件信息 相当于就是得到所有的Excel表FileInfo[] files = dInfo.GetFiles();//数据表容器DataTableCollection tableConllection;for (int i = 0; i < files.Length; i++){//如果不是excel文件就不要处理了if (files[i].Extension != ".xlsx" &&files[i].Extension != ".xls")continue;//打开一个Excel文件得到其中的所有表的数据using (FileStream fs = files[i].Open(FileMode.Open, FileAccess.Read)){IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(fs);tableConllection = excelReader.AsDataSet().Tables;fs.Close();}//遍历文件中的所有表的信息foreach (DataTable table in tableConllection){//生成数据结构类GenerateExcelDataClass(table);//生成容器类GenerateExcelContainer(table);//生成2进制数据GenerateExcelBinary(table);}}}/// <summary>/// 生成Excel表对应的数据结构类/// </summary>/// <param name="table"></param>private static void GenerateExcelDataClass(DataTable table){//字段名行DataRow rowName = GetVariableNameRow(table);//DataRow数据行//字段类型行DataRow rowType = GetVariableTypeRow(table);//判断路径是否存在 没有的话 就创建文件夹if (!Directory.Exists(DATA_CLASS_PATH))Directory.CreateDirectory(DATA_CLASS_PATH);//如果我们要生成对应的数据结构类脚本 其实就是通过代码进行字符串拼接 然后存进文件就行了string str = "public class " + table.TableName + "\n{\n";//变量进行字符串拼接for (int i = 0; i < table.Columns.Count; i++){str += "    public " + rowType[i].ToString() + " " + rowName[i].ToString() + ";\n";}str += "}";//把拼接好的字符串存到指定文件中去File.WriteAllText(DATA_CLASS_PATH + table.TableName + ".cs", str);//刷新Project窗口AssetDatabase.Refresh();}/// <summary>/// 生成Excel表对应的数据容器类/// </summary>/// <param name="table"></param>private static void GenerateExcelContainer(DataTable table){//得到主键索引int keyIndex = GetKeyIndex(table);//得到字段类型行DataRow rowType = GetVariableTypeRow(table);//没有路径创建路径if (!Directory.Exists(DATA_CONTAINER_PATH))Directory.CreateDirectory(DATA_CONTAINER_PATH);string str = "using System.Collections.Generic;\n";str += "public class " + table.TableName + "Container" + "\n{\n";str += "    ";str += "public Dictionary<" + rowType[keyIndex].ToString() + ", " + table.TableName + ">";str += "dataDic = new " + "Dictionary<" + rowType[keyIndex].ToString() + ", " + table.TableName + ">();\n";str += "}";File.WriteAllText(DATA_CONTAINER_PATH + table.TableName + "Container.cs", str);//刷新Project窗口AssetDatabase.Refresh();}/// <summary>/// 生成excel2进制数据/// </summary>/// <param name="table"></param>private static void GenerateExcelBinary(DataTable table){//没有路径创建路径if (!Directory.Exists(BinaryDataMgr.DATA_BINARY_PATH))Directory.CreateDirectory(BinaryDataMgr.DATA_BINARY_PATH);//创建一个2进制文件进行写入using (FileStream fs = new FileStream(BinaryDataMgr.DATA_BINARY_PATH + table.TableName + ".tang", FileMode.OpenOrCreate, FileAccess.Write)){//存储具体的excel对应的2进制信息//1.先要存储我们需要写多少行的数据 方便我们读取//-4的原因是因为 前面4行是配置规则 并不是我们需要记录的数据内容fs.Write(BitConverter.GetBytes(table.Rows.Count - 4), 0, 4);//2.存储主键的变量名string keyName = GetVariableNameRow(table)[GetKeyIndex(table)].ToString();byte[] bytes = Encoding.UTF8.GetBytes(keyName);//存储字符串字节数组的长度fs.Write(BitConverter.GetBytes(bytes.Length), 0, 4);//存储字符串字节数组fs.Write(bytes, 0, bytes.Length);//遍历所有内容的行 进行2进制的写入DataRow row;//得到类型行 根据类型来决定应该如何写入数据DataRow rowType = GetVariableTypeRow(table);for (int i = BEGIN_INDEX; i < table.Rows.Count; i++){//得到一行的数据row = table.Rows[i];for (int j = 0; j < table.Columns.Count; j++){switch (rowType[j].ToString()){case "int":fs.Write(BitConverter.GetBytes(int.Parse(row[j].ToString())), 0, 4);break;case "float":fs.Write(BitConverter.GetBytes(float.Parse(row[j].ToString())), 0, 4);break;case "bool":fs.Write(BitConverter.GetBytes(bool.Parse(row[j].ToString())), 0, 1);break;case "string":bytes = Encoding.UTF8.GetBytes(row[j].ToString());//写入字符串字节数组的长度fs.Write(BitConverter.GetBytes(bytes.Length), 0, 4);//写入字符串字节数组fs.Write(bytes, 0, bytes.Length);break;}}}fs.Close();}AssetDatabase.Refresh();}/// <summary>/// 获取变量名所在行/// </summary>/// <param name="table"></param>/// <returns></returns>private static DataRow GetVariableNameRow(DataTable table){return table.Rows[0];}/// <summary>/// 获取变量类型所在行/// </summary>/// <param name="table"></param>/// <returns></returns>private static DataRow GetVariableTypeRow(DataTable table){return table.Rows[1];}/// <summary>/// 获取主键索引/// </summary>/// <param name="table"></param>/// <returns></returns>private static int GetKeyIndex(DataTable table){DataRow row = table.Rows[2];for (int i = 0; i < table.Columns.Count; i++){if (row[i].ToString() == "key")return i;}return 0;}
}

🎶(8 BinaryData管理器


using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using UnityEngine;/// <summary>
/// 2进制数据管理器
/// </summary>
public class BinaryDataMgr
{/// <summary>/// 2进制数据存储位置路径/// </summary>public static string DATA_BINARY_PATH = Application.streamingAssetsPath + "/Binary/";/// <summary>/// 用于存储所有Excel表数据的容器/// </summary>private Dictionary<string, object> tableDic = new Dictionary<string, object>();/// <summary>/// 数据存储的位置/// </summary>private static string SAVE_PATH = Application.persistentDataPath + "/Data/";private static BinaryDataMgr instance = new BinaryDataMgr();public static BinaryDataMgr Instance => instance;private BinaryDataMgr(){InitData();}public void InitData(){//在此处编写初始化数据}/// <summary>/// 加载Excel表的2进制数据到内存中 /// </summary>/// <typeparam name="T">容器类名</typeparam>/// <typeparam name="K">数据结构类类名</typeparam>public void LoadTable<T,K>(){//读取 excel表对应的2进制文件 来进行解析using (FileStream fs = File.Open(DATA_BINARY_PATH + typeof(K).Name + ".tang", FileMode.Open, FileAccess.Read)){byte[] bytes = new byte[fs.Length];fs.Read(bytes, 0, bytes.Length);fs.Close();//用于记录当前读取了多少字节了int index = 0;//读取多少行数据int count = BitConverter.ToInt32(bytes, index);index += 4;//读取主键的名字int keyNameLength = BitConverter.ToInt32(bytes, index);index += 4;string keyName = Encoding.UTF8.GetString(bytes, index, keyNameLength);index += keyNameLength;//创建容器类对象Type contaninerType = typeof(T);object contaninerObj = Activator.CreateInstance(contaninerType);//得到数据结构类的TypeType classType = typeof(K);//通过反射 得到数据结构类 所有字段的信息FieldInfo[] infos = classType.GetFields();//读取每一行的信息for (int i = 0; i < count; i++){//实例化一个数据结构类 对象object dataObj = Activator.CreateInstance(classType);foreach (FieldInfo info in infos){if( info.FieldType == typeof(int) ){//相当于就是把2进制数据转为int 然后赋值给了对应的字段info.SetValue(dataObj, BitConverter.ToInt32(bytes, index));index += 4;}else if (info.FieldType == typeof(float)){info.SetValue(dataObj, BitConverter.ToSingle(bytes, index));index += 4;}else if (info.FieldType == typeof(bool)){info.SetValue(dataObj, BitConverter.ToBoolean(bytes, index));index += 1;}else if (info.FieldType == typeof(string)){//读取字符串字节数组的长度int length = BitConverter.ToInt32(bytes, index);index += 4;info.SetValue(dataObj, Encoding.UTF8.GetString(bytes, index, length));index += length;}}//读取完一行的数据了 应该把这个数据添加到容器对象中//得到容器对象中的 字典对象object dicObject = contaninerType.GetField("dataDic").GetValue(contaninerObj);//通过字典对象得到其中的 Add方法MethodInfo mInfo = dicObject.GetType().GetMethod("Add");//得到数据结构类对象中 指定主键字段的值object keyValue = classType.GetField(keyName).GetValue(dataObj);mInfo.Invoke(dicObject, new object[] { keyValue, dataObj });}//把读取完的表记录下来tableDic.Add(typeof(T).Name, contaninerObj);fs.Close();}}/// <summary>/// 得到一张表的信息/// </summary>/// <typeparam name="T">容器类名</typeparam>/// <returns></returns>public T GetTable<T>() where T:class{string tableName = typeof(T).Name;if (tableDic.ContainsKey(tableName))return tableDic[tableName] as T;return null;}/// <summary>/// 存储类对象数据/// </summary>/// <param name="obj"></param>/// <param name="fileName"></param>public void Save(object obj, string fileName){//先判断路径文件夹有没有if (!Directory.Exists(SAVE_PATH))Directory.CreateDirectory(SAVE_PATH);using (FileStream fs = new FileStream(SAVE_PATH + fileName + ".tang", FileMode.OpenOrCreate, FileAccess.Write)){BinaryFormatter bf = new BinaryFormatter();bf.Serialize(fs, obj);fs.Close();}}/// <summary>/// 读取2进制数据转换成对象/// </summary>/// <typeparam name="T"></typeparam>/// <param name="fileName"></param>/// <returns></returns>public T Load<T>(string fileName) where T:class{//如果不存在这个文件 就直接返回泛型对象的默认值if( !File.Exists(SAVE_PATH + fileName + ".tang") )return default(T);T obj;using (FileStream fs = File.Open(SAVE_PATH + fileName + ".tang", FileMode.Open, FileAccess.Read)){BinaryFormatter bf = new BinaryFormatter();obj = bf.Deserialize(fs) as T;fs.Close();}return obj;}
}

2.刷新Project窗口内容

因为我们用代码创建完文件后需要被刷新之后才可以看到

    //  Directory.CreateDirectory(Application.dataPath + "/测试文件夹");AssetDatabase.Refresh();

在这里插入图片描述

🅰️系统路线学习点击跳转


👨‍💻 Unity程序基础学习路线🧧
⭐【Unityc#专题篇】之c#进阶篇】🎁
⭐【Unityc#专题篇】之c#核心篇】🎁
⭐【Unityc#专题篇】之c#基础篇】🎁
⭐【Unity-c#专题篇】之c#入门篇】🎁
【Unityc#专题篇】—进阶章题单实践练习🎁
⭐【Unityc#专题篇】—基础章题单实践练习🎁
【Unityc#专题篇】—核心章题单实践练习🎁

你们的点赞👍 收藏⭐ 留言📝 关注✅是我持续创作,输出优质内容的最大动力!


在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/41614.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑硬盘分区的基本步骤(2个实用的硬盘分区方法)

在现代计算机中&#xff0c;硬盘分区是非常重要的一步。无论是新硬盘的初始化&#xff0c;还是重新组织现有硬盘&#xff0c;分区都是必不可少的操作。本文将详细介绍电脑硬盘分区的基本步骤&#xff0c;帮助您更好地管理和利用硬盘空间。 文章开始&#xff0c;我们先简单说一…

【C++】 解决 C++ 语言报错:Invalid Conversion from ‘const char*’ to ‘char*’

文章目录 引言 在 C 编程中&#xff0c;类型转换错误&#xff08;Invalid Conversion&#xff09;是常见的编译错误之一。特别是当程序试图将一个常量字符指针&#xff08;const char*&#xff09;转换为非常量字符指针&#xff08;char*&#xff09;时&#xff0c;会导致编译…

Vmware环境下ESXi主机 配置上行链路、虚拟交换机、端口组、VMkernel网卡

一、适用场景 1、使用专业服务器跑多种不同的业务&#xff0c;每种业务可能所需运行的server环境不同&#xff0c;有的需要Linux server CentOS7/8、kali、unbuntu……有的需要windows server2008、2003、2016、2019、2022…… 2、本例采用的是VMware ESXi6.7 update 3版本&am…

力扣习题--找不同

目录 前言 题目和解析 1、找不同 2、 思路和解析 总结 前言 本系列的所有习题均来自于力扣网站LeetBook - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台 题目和解析 1、找不同 给定两个字符串 s 和 t &#xff0c;它们只包含小写字母。 字符串 t…

Java Maven中自动代码检查插件详细介绍

文章目录 Checkstyle主要特点使用场景配置与使用checkstyle.xmlsuppressions.xml 验证打包时验证执行命令验证 Spotless配置文件内容Java配置部分POM 配置部分Markdown 配置部分Up to Date Checking执行部分 验证打包时验证在插件中执行命令验证 Checkstyle Spotless 结合chec…

redis学习(005 java客户端 RedisTemplate学习)

黑马程序员Redis入门到实战教程&#xff0c;深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目 总时长 42:48:00 共175P 此文章包含第16p-第p23的内容 文章目录 java客户端jedisSpringDataRedis项目实现hash哈希操作 java客户端 jedis 测试 ps:如果连接不上&…

vs2019 无法打开项目文件

vs2019 无法打开项目文件&#xff0c;无法找到 .NET SDK。请检查确保已安装此项且 global.json 中指定的版本(如有)与所安装的版本相匹配 原因&#xff1a;缺少组件 解决方案&#xff1a;选择需要的组件进行安装完成

步进电机改伺服电机

步进电机&#xff1a; 42&#xff1a;轴径5mm 57&#xff1a;轴径8mm 86&#xff1a;轴径14mm 【86CME120闭环】// 12牛米 伺服电机&#xff1a; 40&#xff1a; 60&#xff1a; 80&#xff1a; 86&#xff1a; ECMA——C 1 0910 R S 4.25A 轴径…

评价ChatGPT与强人工智能的未来

在人工智能领域&#xff0c;ChatGPT的出现无疑是一个里程碑事件。它不仅展示了自然语言处理技术的巨大进步&#xff0c;也引发了人们对于强人工智能&#xff08;AGI&#xff09;的无限遐想。本文将从多个角度评价ChatGPT&#xff0c;并探讨强人工智能距离我们还有多远。 ChatGP…

无人机运营合格证及无人机驾驶员合格证(AOPA)技术详解

无人机运营合格证及无人机驾驶员合格证&#xff08;AOPA&#xff09;技术详解如下&#xff1a; 一、无人机运营合格证 无人机运营合格证是无人机运营企业或个人必须获得的证书&#xff0c;以确保无人机在运营过程中符合相关法规和标准。对于无人机运营合格证的具体要求和申请…

无人机人员搜救

人员搜救-水域救援 水域搜救&#xff1a;快速水面搜查 物资抛投&#xff1a;救生物资抛投 绳索牵引&#xff1a;牵引救援绳索 领航船艇&#xff1a;水面侦察领航 人员搜救 昼夜搜救&#xff0c;精准定位 水域搜救 经纬 M300 RTK 搭载禅思 H20T 能够满足全天候作业需求&a…

新手教学系列——Git Stash踩坑

在之前的文章《如何彻底避免Git代码相互覆盖问题》中,我曾介绍过通过规范分支合并和使用git stash来避免代码覆盖问题。今天,我要深入探讨一下git stash的使用,并分享一些使用过程中遇到的坑,希望能帮你避免类似问题。 脚本mg.sh简介 为了更好地管理代码合并,我编写了一…

linux之管道重定向

管道与重定向 一、重定向 将原输出结果存储到其他位置的过程 标准输入、标准正确输出、标准错误输出 ​ 进程在运行的过程中根据需要会打开多个文件&#xff0c;每打开一个文件会有一个数字标识。这个标识叫文件描述符。 进程使用文件描述符来管理打开的文件&#xff08;FD--…

windows USB 设备驱动开发-控制传输的数据包

每次在主机控制器和 USB 设备之间移动数据时&#xff0c;都会发生传输。 通常&#xff0c;USB 传输可大致分为控制传输和数据传输。 所有 USB 设备都必须支持控制传输&#xff0c;并且可以支持用于数据传输的端点。 每种类型的传输都与设备缓冲区USB 端点 的类型相关联。 控制传…

泛微开发修炼之旅--32ecology对接海康威视综合安防管理系统,人脸识别机器数据同步代码方案及源码

文章链接&#xff1a;32ecology对接海康威视综合安防管理系统&#xff0c;人脸识别机器数据同步代码方案及源码

Open3D 在点云中构建八叉树

目录 一、概述 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2构建后点云 一、概述 八叉树&#xff08;Octree&#xff09;是一种树状数据结构&#xff0c;用于递归地将3D空间分割成较小的立方体。八叉树特别适用于3D计算机图形学、点云处理和空间…

[图解]企业应用架构模式2024新译本讲解22-标识映射

1 00:00:01,080 --> 00:00:04,710 我们来看一下标识映射这个模式 2 00:00:08,030 --> 00:00:10,110 它是属于对象-关系 3 00:00:10,120 --> 00:00:11,150 行为模式 4 00:00:11,160 --> 00:00:13,890 就是说&#xff0c;在动态的时候 5 00:00:15,770 --> 00:…

C# Application.DoEvents()的作用

文章目录 1、详解 Application.DoEvents()2、示例处理用户事件响应系统事件控制台输出游戏和多媒体应用与操作系统的交互 3、注意事项总结 Application.DoEvents() 是 .NET 框架中的一个方法&#xff0c;它主要用于处理消息队列中的事件。在 Windows 应用程序中&#xff0c;当一…

实验四 图像增强—灰度变换之直方图变换

一&#xff0e;实验目的 1&#xff0e;掌握灰度直方图的概念及其计算方法&#xff1b; 2&#xff0e;熟练掌握直方图均衡化计算过程&#xff1b;了解直方图规定化的计算过程&#xff1b; 3&#xff0e;了解色彩直方图的概念和计算方法 二&#xff0e;实验内容&#xff1a; …

课设:选课管理系统(Java+MySQL)

在本博客中&#xff0c;我将介绍用Java、MySQL、JDBC和Swing GUI开发一个简单的选课管理系统。 技术栈 Java&#xff1a;用于编写应用程序逻辑MySQL&#xff1a;用于存储和管理数据JDBC&#xff1a;用于连接Java应用程序和MySQL数据库Swing GUI&#xff1a;用于构建桌面应用程…