UE5.3 C++ 房屋管理系统(二)
三.当房屋生成成功,我们就需要把TMap里的数据存到数据库里。不然一点停止运行,就会所以数据都不见了。这里使用DataTable来存储。
1.DataTable是UE常用的表,虽然不是专门用来存档的,但也可以这么用。
DataTable表,实际是每一行的名字,对于每一行的内容。它可以根据你的结构体自动转换为表的每一行。
我们首先创造结构体,继承自TableRowBase。就是表行的基类,里面的数据类型,和TMap里BuildInfo保持一致,方便同步。
struct FBuildTableStruct:public FTableRowBase
{GENERATED_USTRUCT_BODY();UPROPERTY(EditAnywhere)int ID = 0;//类型UPROPERTY(EditAnywhere, BlueprintReadWrite)FString Type = "";UPROPERTY(EditAnywhere, BlueprintReadWrite)int Area = 100;//使用人数()//蓝图可访问通信UPROPERTY(EditAnywhere, BlueprintReadWrite)int ResidentPopulation = 100;//价值()
//蓝图可访问通信UPROPERTY(EditAnywhere, BlueprintReadWrite)int Pirce = 100;//位置//蓝图可访问通信UPROPERTY(EditAnywhere, BlueprintReadWrite)FVector Position = FVector::Zero();//方位//蓝图可访问通信UPROPERTY(EditAnywhere, BlueprintReadWrite)FRotator Rotation = FRotator::ZeroRotator;// 大小//蓝图可访问通信UPROPERTY(EditAnywhere, BlueprintReadWrite)FVector Scale = FVector(1, 1, 1);};
创建表,并选择表里的每一行的数据是上面的结构体。
表里的RowName,是系统自动添加的用于标识每一行。一开始表是空的,这是已经存入数据后的样子。
2.我们就写一个ATableManagerActor来管理存储。前面的是通用的,对表Tablet的数据进行增删查改。后面是根据不同的需求,封装了前面对表操作的功能。核心目的就是把 TMap里的数据,随时同步到Table里去。它们之间的主要是靠ID属性对应,RowName 保持和 ID相同。
ATableManagerActor : public AActor
{GENERATED_BODY()public: // Sets default values for this actor's propertiesATableManagerActor();protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public: // Called every framevirtual void Tick(float DeltaTime) override;UFUNCTION(BlueprintCallable, DisplayName = "clearDataTable", Category = "DataTable")void clearDataTable(UDataTable* DataTable);UFUNCTION(BlueprintCallable, DisplayName = "addDataTableRow", Category = "DataTable")void addDataTableRow(UDataTable* DataTable, FName rowName, const FBuildTableStruct& row);UFUNCTION(BlueprintCallable, DisplayName = "removeDataTableRow", Category = "DataTable")void removeDataTableRow(UDataTable* DataTable, FName rowName);UFUNCTION(BlueprintCallable,DisplayName = "EditeDataTableRow",Category = "DataTable")void editeDataTableRow(FBuildTableStruct tmp);//从表里拿所有的信息UFUNCTION(BlueprintCallable, DisplayName = "findAllRow", Category = "DataTable")void findAllRow();//从表里拿删除所有的信息UFUNCTION(BlueprintCallable, DisplayName = "findAllRow", Category = "DataTable")void deletAllRow();UFUNCTION(BlueprintCallable, DisplayName = "saveToALLTable", Category = "DataTable")void saveToALLTable();UFUNCTION(BlueprintCallable, DisplayName = "DataTableToCSV", Category = "DataTable")void DataTableToCSV();UFUNCTION(BlueprintCallable, DisplayName = "DataTableToCSV", Category = "DataTable")FBuildTableStruct GetBuildInfoFromDT(int ID);UFUNCTION(BlueprintCallable, DisplayName = "DataTableToCSV", Category = "DataTable")void CommiteBuildInfo();UFUNCTION(BlueprintCallable, DisplayName = "Inittial", Category = "DataTable")void Inittial();UFUNCTION(BlueprintCallable, DisplayName = "ShowClickBuild",Category = "DataTable")void ShowClickBuildInfo(ABuildBase* curBuid);UFUNCTION()void SetBuildEditUI(ULZJUserWidget* UI);UPROPERTY()UDataTable* BuildInfoDataTable;UPROPERTY()TMap<int,FBuildTableStruct> Rows;UPROPERTY()UBuildManagerInstance* BuildManagerIns;UPROPERTY()UBuildFactory* BuildFactory;//UPROPERTY()ABuildBase* ClickBuild;UPROPERTY()FBuildTableStruct ClicBuildInfo;UPROPERTY()ULZJUserWidget* BuildEditUI;bool isClick;
};
3.我们开始实现,每一行数据存入表中。首先拿到表的资源,再拿到上篇文章的 房屋管理者。然后实现,对表的增删查改。当房屋管理者的TMap发生改变,也对表里的数据进行同样操作。
// Called when the game starts or when spawned
void ATableManagerActor::BeginPlay()
{Super::BeginPlay();BuildInfoDataTable = LoadObject<UDataTable>(this, TEXT("/Script/Engine.DataTable'/LZJCore/DTBuildInfo.DTBuildInfo'"));findAllRow();BuildManagerIns = GetWorld()->GetGameInstance()->GetSubsystem<UBuildManagerInstance>();BuildFactory = GetWorld()->GetGameInstance()->GetSubsystem<UBuildFactory>();//TArray<AActor*> TBActors;//UGameplayStatics::GetAllActorsOfClass(GetWorld(), ATableManagerActor::StaticClass(), TBActors);TArray<UUserWidget*> Actors;//TArray<UUserWidget*>& FoundWidgets, TSubclassOf<UUserWidget> WidgetClass,UWidgetBlueprintLibrary::GetAllWidgetsOfClass(GetWorld(), Actors, ULZJUserWidget::StaticClass());if (!Actors.IsEmpty()){BuildEditUI = Cast<ULZJUserWidget>(Actors[0]);}
}// Called every frame
void ATableManagerActor::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}void ATableManagerActor::clearDataTable(UDataTable* DataTable)
{if (DataTable == nullptr){return;}DataTable->EmptyTable();DataTable->GetOutermost()->MarkPackageDirty();
}void ATableManagerActor::addDataTableRow(UDataTable* DataTable, FName rowName, const FBuildTableStruct& row)
{if (DataTable == nullptr){return;}DataTable->AddRow(rowName, row);DataTable->GetOutermost()->MarkPackageDirty();
}void ATableManagerActor::removeDataTableRow(UDataTable* DataTable, FName rowName)
{if (DataTable == nullptr){return;}DataTable->RemoveRow(rowName);DataTable->GetOutermost()->MarkPackageDirty();
}void ATableManagerActor::editeDataTableRow(FBuildTableStruct tmp)
{if (BuildInfoDataTable->IsValidLowLevel()){FString Str = FString::FromInt(tmp.ID); // 行名FName RowName = FName(Str);FBuildTableStruct* RowData = BuildInfoDataTable->FindRow<FBuildTableStruct>(RowName, TEXT("Context"));if (RowData){RowData->Area = tmp.Area;RowData->Pirce = tmp.Pirce;RowData->ResidentPopulation = tmp.ResidentPopulation;//RowData->= tmp.Area;BuildInfoDataTable->MarkPackageDirty(); // 标记为需要保存}}}void ATableManagerActor::findAllRow()
{if (BuildInfoDataTable->IsValidLowLevel()){//BuildInfoDataTable->GetTableData();if (!BuildInfoDataTable) return;TArray<FName> RowNames = BuildInfoDataTable->GetRowNames();for (const auto& Name : RowNames){for (auto it : BuildInfoDataTable->GetRowMap()){FString rowName = (it.Key).ToString();//FBuildTableStruct为你的FStructFBuildTableStruct* pRow = (FBuildTableStruct*)it.Value;//输出需根据你的FStruct进行调整//UE_LOG(LogTemp, Warning, TEXT("read by traversal --- RowName:%s, Name:%s, price:%d, introduct:%s"), *rowName, *(pRow->ID), pRow->ProductPrice, *(pRow->ProductIntroduce));Rows.Add(pRow->ID,*pRow);}}}
}void ATableManagerActor::deletAllRow()
{}void ATableManagerActor::saveToALLTable()
{if (BuildInfoDataTable->IsValidLowLevel()){//BuildInfoDataTable->GetTableData();if (!BuildInfoDataTable) return;TArray<FName> RowNames = BuildInfoDataTable->GetRowNames();TMap<int, ABuildBase*> Cpoy = BuildManagerIns->m_TargetMap; //拷贝值for (auto& Elem : Cpoy){ABuildBase* curBuildBase = Elem.Value;FBuildTableStruct* BuildInfo = new FBuildTableStruct(); //结构体BuildInfo->ID = curBuildBase->m_targetID;FString IntString = FString::FromInt(BuildInfo->ID);FName RowName = FName(*IntString);BuildInfo->Area = curBuildBase->m_Area;BuildInfo->ResidentPopulation = curBuildBase->m_ResidentPopulation;BuildInfo->Pirce = curBuildBase->m_Price;//BuildInfo->ResidentPopulation = curBuildBase->m_ResidentPopulation;BuildInfo->Type = curBuildBase->m_Type;BuildInfo->Position = curBuildBase->m_Position;BuildInfo->Rotation = curBuildBase->m_Rotation;BuildInfoDataTable->AddRow(RowName, *BuildInfo);}保存为资产/*FString PackageName = TEXT("/Game/Data/DynamicDataTable");UPackage* Package = CreatePackage(*PackageName);DynamicDataTable->Rename(*FPaths::GetBaseFilename(PackageName), Package);Package->MarkPackageDirty();FAssetRegistryModule::AssetCreated(DynamicDataTable);FString PackageFileName = FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension());bool bSaved = UPackage::SavePackage(Package,DynamicDataTable,RF_Public | RF_Standalone,*PackageFileName);if (bSaved){UE_LOG(LogTemp, Log, TEXT("Dynamic DataTable saved successfully!"));}*///UPackage* Package = FindPackage(nullptr, *FPackageName::FilenameToLongPackageName(BuildInfoDataTable->GetPathName()));//if (Package)//{// Package->SetDirtyFlag(true);//const TSoftObjectPtr<UDataTable> SourceDataTable = BuildInfoDataTable;//UEditorAssetLibrary::SaveAsset(SourceDataTable, false);//}}/*Tarray<UPackage*>PackageToSave;PackageToSave.Add(Table->GetOutermost());FEditorFileUtils::EPromptReturnCode RetValue = FEditorFileUtils::PromptForCheckoutAndSave(PackageToSave, false, false);*/TArray<UPackage*> PackagesToSave;PackagesToSave.Add(BuildInfoDataTable->GetOutermost());FEditorFileUtils::PromptForCheckoutAndSave(PackagesToSave, false, /*bPromptToSave=*/ false);
}void ATableManagerActor::DataTableToCSV()
{FString Path = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo2.csv");Path = FPaths::ConvertRelativePathToFull(*Path);FPlatformFileManager::Get().Get().GetPlatformFile().DeleteFile(*Path);if (BuildInfoDataTable){FString CSVString = BuildInfoDataTable->GetTableAsCSV();FString CSVPath = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo2.csv");FFileHelper::SaveStringToFile(CSVString, *CSVPath, FFileHelper::EEncodingOptions::ForceUTF8);}
}FBuildTableStruct ATableManagerActor::GetBuildInfoFromDT(int ID)
{FBuildTableStruct tmp;if (BuildInfoDataTable->IsValidLowLevel()){FString Str = FString::FromInt(ID); // 行名FName RowName = FName(Str);FBuildTableStruct* RowData = BuildInfoDataTable->FindRow<FBuildTableStruct>(RowName, TEXT("Context"));if (RowData){// 使用找到的数据UE_LOG(LogTemp, Warning, TEXT("Health: %d"), RowData->ID);tmp = *RowData;}else{UE_LOG(LogTemp, Warning, TEXT("Row not found!"));}}return tmp;
}void ATableManagerActor::CommiteBuildInfo()
{FBuildTableStruct tmp;}void ATableManagerActor::Inittial()
{findAllRow();//TMap<int, FBuildTableStruct> Rows;// 假设MyMap已有数据...//BuildManagerIns->InitialBuilds(Rows);//for (auto It = Rows.CreateIterator(); It; ++It) {// int ID = It.Key(); // 获取键// FBuildTableStruct Build = It.Value(); // 获取值// //UE_LOG(LogTemp, Warning, TEXT("Key: %s, Value: %d"), *Key, Value);//}BuildFactory->InitialBuilds(Rows);
}//拿到点击的 ID,并查表拿到它的建筑的信息》
void ATableManagerActor::ShowClickBuildInfo(ABuildBase* curBuid)
{if (curBuid->IsValidLowLevel()){int ID = curBuid->m_targetID;ClicBuildInfo = GetBuildInfoFromDT(ID);isClick = true;if (BuildEditUI){BuildEditUI->ShowEditBuildInfo(ClicBuildInfo);}}else{return;}isClick = false;
}void ATableManagerActor::SetBuildEditUI(ULZJUserWidget* UI)
{BuildEditUI = UI;
}
这里将DataTable 导入到CSV,使用的是DataTable里的API, GetTableAsCSV();
void ATableManagerActor::DataTableToCSV()
{FString Path = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo2.csv");Path = FPaths::ConvertRelativePathToFull(*Path);FPlatformFileManager::Get().Get().GetPlatformFile().DeleteFile(*Path);if (BuildInfoDataTable){FString CSVString = BuildInfoDataTable->GetTableAsCSV();FString CSVPath = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo2.csv");FFileHelper::SaveStringToFile(CSVString, *CSVPath, FFileHelper::EEncodingOptions::ForceUTF8);}
}
相关文章:

UE5.3 C++ 房屋管理系统(二)
三.当房屋生成成功,我们就需要把TMap里的数据存到数据库里。不然一点停止运行,就会所以数据都不见了。这里使用DataTable来存储。 1.DataTable是UE常用的表,虽然不是专门用来存档的,但也可以这么用。 DataTable表,实…...

VSCode1.101.0便携版|中英文|编辑器|安装教程
软件介绍 Visual Studio Code是微软推出的一个强大的代码编辑器,功能强大,操作简单便捷,还有着良好的用户界面,设计得很人性化,旨在为所有开发者提供一款专注于代码本身的免费的编辑器。 软件安装 1、 下载安装包…...

Linux系统发布.net core程序
前端 前端用的Vue3,发布的话需要Nginx下载安装Nginx 麒麟:这里我麒麟用的是桌面版,我直接把操作流程写在下面,写的比较简单,具体的可以具体搜这一块内容学习一下。打包vue程序,通过MobaXterm将打包后的程序…...
当需要在一个方法中清除多个缓存时,@CacheEvict注解能否实现这个需求
想清除Redis中的多个缓存数据,如何实现? CacheEvict清除一个缓存,但现在想知道如何处理多个缓存的情况。场景:可能有一个更新用户信息的方法,这个方法执行后,不仅需要清除某个特定的用户缓存,还…...

极新携手火山引擎,共探AI时代生态共建的破局点与增长引擎
在生成式AI与行业大模型的双重驱动下,人工智能正以前所未有的速度重构互联网产业生态。从内容创作、用户交互到商业决策,AI技术渗透至产品研发、运营的全链条,推动效率跃升与创新模式变革。然而,面对AI技术迭代的爆发期࿰…...
Score-CAM:卷积神经网络的评分加权视觉解释
摘要 最近,越来越多的关注被引向卷积神经网络的内部机制,以及网络为何会做出特定决策。本文中,我们开发了一种基于类别激活映射的新颖事后可视化解释方法,称为Score-CAM。与以往基于类别激活映射的方法不同,Score-CAM通过前向传递得分获取每个激活图的权重,从而摆脱了对…...
Python刷题练习
文章目录 1.寻找相同字串2.密钥格式化3.五键键盘的输出4.单词重量5.输出指定字母在字符串的中的索引6.污染水域7.九宫格按键输入8.任务最优调度9.高效的任务规划 1.寻找相同字串 题目描述: 给你两个字符串t和p,要求从t中找到一个和p相同的连续子串,并输…...

对比 HTTP-REST 与 gRPC:各自的优缺点以及适用的场景
文章目录 对比 HTTP-REST 与 gRPC:各自的优缺点以及适用的场景HTTP-REST 与 gRPC 的核心区别gRPC 的优缺点HTTP-REST 的优缺点适用场景 模糊点什么是 Protobuf?HTTP/2 会将 HTTP 消息拆分并封装为二进制帧,那还能过使用 HTTP/2 构建 RESTful …...

Git - 1( 14000 字详解 )
一: Git 初识 1.1 提出问题 在工作或学习中,我们常常会面临文档管理的问题,尤其是在编写各种文档时。为了防止文档丢失或因更改失误而无法恢复,我们常常会创建多个版本的副本,例如:“报告-v1”、“报告-v…...

TCPIP详解 卷1协议 九 广播和本地组播(IGMP 和 MLD)
9.1——广播和本地组播(IGMP 和 MLD) IPv4可以使用4种IP地址:单播(unicast)、任播(anycast)、组播(multicast)和广播(broadcast)。 IPv6可以使用…...

16.1 - VDMA视频转发实验之TPG
文章目录 1 实验任务2 系统框图3 硬件设计3.1 IP核配置3.2 注意事项 4 软件设计4.1 注意事项4.2 工程源码4.2.1 main.c文件 1 实验任务 基于14.1,使用Xilinx TPG(Test Pattern Generator) IP提供视频源,将视频数据通过VDMA写入PS…...

cocos creator 3.8 下的 2D 改动
在B站找到的系统性cocos视频教程,纯2D开发入门,链接如下: zzehz黑马程序员6天实战游戏开发微信小程序(Cocos2d的升级版 CocosCreator JavaScript)_哔哩哔哩_bilibili黑马程序员6天实战游戏开发微信小程序(Cocos2d的升级版 CocosCreator Ja…...
Vue3 + Element Plus 动态表单实现
完整代码 <template><div class"dynamic-form-container"><el-formref"dynamicFormRef":model"formData":rules"formRules"label-width"auto"label-position"top"v-loading"loading"&g…...
【WPF】Opacity 属性的使用
在WPF(Windows Presentation Foundation)中,Opacity 属性是定义一个元素透明度的属性,其值范围是从 0.0(完全透明)到 1.0(完全不透明)。由于 Opacity 是在 UIElement 类中定义的&…...

Unity光照笔记
问题 在做项目中遇到了播放中切换场景后地面阴影是纯黑的问题,不得不研究一下光照。先放出官方文档。 Lighting 窗口 - Unity 手册 播放中切换场景后地面阴影是纯黑 只有投到地面的阴影是纯黑的。且跳转到使用相同Terrain的场景没有问题。 相关文章:…...
Linux中安装samba服务
在Linux服务器上安装Samba可以实现文件共享功能,下面为你详细介绍安装步骤: 一、安装Samba 不同的Linux发行版使用不同的命令来安装Samba: Debian/Ubuntu: sudo apt update sudo apt install sambaCentOS/RHEL: s…...
猫咪如厕检测与分类识别系统系列~进阶【三】网页端算法启动架构及数据库实现
前情提要 家里养了三只猫咪,其中一只布偶猫经常出入厕所。但因为平时忙于学业,没法时刻关注牠的行为。我知道猫咪的如厕频率和时长与健康状况密切相关,频繁如厕可能是泌尿问题,停留过久也可能是便秘或不适。为了更科学地了解牠的如…...
Elasticsearch性能调优全攻略:从日志分析到集群优化
#作者:猎人 文章目录 前言搜索慢查询日志索引慢写入日志性能调优之基本优化建议性能调优之索引写入性能优化提升es集群写入性能方法:性能调优之集群读性能优化性能调优之搜索性能优化性能调优之GC优化性能调优之路由优化性能调优之分片优化 前言 es里面…...

嵌入式学习的第二十天-数据结构-调试+链表的一般操作
一、调试 1.一般调试 2.找段错误 二、链表的一般操作 1.单链表的修改 int ModifyLinkList(LinkList*ll,char*name,DATATYPE*data) {DATATYPE * tmp FindLinkList(ll, name);if(NULL tmp){return 1;}memcpy(tmp,data,sizeof(DATATYPE));return 0; } 2.单链表的销毁 int D…...
Leetcode 3548. Equal Sum Grid Partition II
Leetcode 3548. Equal Sum Grid Partition II 1. 解题思路2. 代码实现 题目链接:3548. Equal Sum Grid Partition II 1. 解题思路 这一题是题目3546. Equal Sum Grid Partition I的进阶版本,不过本质上还是差不多的。 相较于题目3546,这里…...

家具制造行业的现状 质检LIMS如何赋能家具制造企业质检升级
在家具制造行业,从原木切割到成品出厂,质检环节贯穿始终 —— 木材含水率是否达标、板材甲醛释放量是否合规、涂层耐磨性能否通过标准…… 这些看似琐碎的检测项目,实则是企业把控产品品质、规避市场风险的核心关卡。传统人工质检模式在效率、…...

idea整合maven环境配置
idea整合maven 提示:帮帮志会陆续更新非常多的IT技术知识,希望分享的内容对您有用。本章分享的是springboot的使用。前后每一小节的内容是存在的有:学习and理解的关联性。【帮帮志系列文章】:每个知识点,都是写出代码…...

无偿帮写毕业论文(看不懂的可以私信博主)
以下教程教你如何利用相关网站和AI免费帮你写一个毕业论文。毕竟毕业论文只要过就行,脱产学习这么多年,终于熬出头了,完成毕设后有空就去多看看亲人好友,祝好! 一、找一个论文模板 废话不多说,先上干货Ov…...

小白成长之路-vim编辑
文章目录 Vim一、命令模式二、插入模式3.a:进入插入模式,在当前光标的后一个字符插入4.o: 在当前光标的下一行插入5.i:在当前光标所在字符插入,返回命令模…...
Java 开源报表系统全解析:免费工具、企业案例与集成实践
在企业级数据可视化与报表开发中,选择一款功能强大且完全免费的开源报表系统至关重要。本文深度剖析 5 款经过权威验证的免费开源 Java 报表工具,涵盖图表展示、定制化及第三方集成能力,附企业级案例与技术实践,助您高效选型。 一…...

【常用算法:排序篇】7.算法魔法与面试秘籍:从趣味排序到实战通关
一、趣味排序算法:突破常规的思维火花 1. 睡眠排序(Sleep Sort)—— 时间维度的魔法 核心思想:利用多线程休眠时间模拟数值大小,自然输出有序结果。Python示例:import threading import timedef sleep_so…...
前端npm的核心作用与使用详解
一、npm是什么? npm(Node Package Manager) 是 Node.js 的默认包管理工具,也是全球最大的开源代码库生态系统。虽然它最初是为 Node.js 后端服务设计的,但如今在前端开发中已成为不可或缺的基础设施。通过npm,开发者可以轻松安装、管理和共享代码模块。 特性: 依赖管理…...

Android | IOS — Solox性能测试
文章目录 Solox性能测试1. 前置条件2. 软件图片 Solox性能测试 1. 前置条件 安装Python:3.10.0以上版本: Windows:Python官网 安装 SoloX python -m solox2. 软件图片 软件图片 报告分析:...
Rust 数据结构:Vector
Rust 数据结构:Vector Rust 数据结构:Vector创建数组更新数组插入元素删除元素 获取数组中的元素迭代数组中的值使用枚举存储多个类型删除一个数组会删除它的元素 Rust 数据结构:Vector vector 来自标准库,在内存中连续存储相同类…...
探索Turn.js:打造惊艳的3D翻页效果
目录 简介与特性 环境准备与安装 基础用法与初始化 配置参数详解 事件监听与交互 动态加载与页面管理 兼容性与性能优化 常见问题与解决方案 完整示例代码 1. 简介与特性 Turn.js 是一个基于 jQuery 的 JavaScript 库,专注于实现类书籍翻页的 3D 动画效果…...