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

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里去。

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

相关文章:

  • PyTorch 中的 Autograd 实现细节解析和应用
  • Go语言:json 作用和语法
  • 请解释 React Native 的新架构(Fabric 和 TurboModules)与旧架构的主要区别
  • Golang企业级商城高并发微服务实战
  • 集成指南:如何采用融云 Flutter IMKit 实现双端丝滑社交体验
  • hiveserver2与beeline进行远程连接hive配置及遇到的问题
  • #S4U2SELF#S4U2Proxy#CVE-2021-42278/42287
  • DeepWiki: Github的百科全书
  • MCP与GitHub的集成:开发者的“自动化流水线”革命
  • 什么是ERP?ERP有哪些功能?小微企业ERP系统源码,SpringBoot+Vue+ElementUI+UniAPP
  • 傲云源墅:以五傲价值重构北京主城别墅格局
  • 自动发电控制是一次调频还是二次调频?
  • Java面试终极篇:Sentinel+Seata+Kafka Streams高并发架构实战
  • Redis+Caffeine构造多级缓存
  • 数据库原理期末考试速成--最后附带两套题
  • 基于大模型的原发性醛固酮增多症全流程预测与诊疗方案研究
  • 硅基计划2.0 学习总结 壹 Java初阶
  • 在Mac环境下搭建Docker环境的全攻略
  • 红队视角下的域森林突破:一场由Shiro反序列化引发的跨域控攻防对抗
  • [Git]ssh下用Tortoisegit每次提交都要输密码
  • 高适配算力、行业大模型与智能体平台重塑工业城市
  • 马上评丨摆摊要交芙蓉王?对吃拿卡要必须零容忍
  • 韩国执政党总统候选人更换方案被否决,金文洙候选人资格即刻恢复
  • 巴称巴控克什米尔地区11人在印方夜间炮击中身亡
  • 被取消总统候选人资格,金文洙:将采取政治法律措施讨回公道
  • 聆听百年唐调正声:唐文治王蘧常吟诵传习的背后