一.总体思路
首先使用管理者获得TileSet,通过JSON文件读写,调用对应的Cesium内部提供的函数。
UE5中Json文件的读取与解析 - 知乎 (zhihu.com) 不太了解JSON的可以学习这个。
二.具体实现
1.创建Actor,并且
如何获得Cesium的TileSet,设置本地Url
一.首先使用管理者获得TileSet
二.通过JSON文件读写
三.设置CesiumMap
1.首先前置声明两个可以直接设置组件,一个定时器负责定时读取JSON。
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "UrlManager.generated.h"
class ACesium3DTileset;
class UCesiumTileMapServiceRasterOverlay;
UCLASS()
class HMSLIVEEARTH_API AUrlManager : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AUrlManager();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
ACesium3DTileset* CesiumTil;
UCesiumTileMapServiceRasterOverlay* CesiumRas;
//声明定时器
FTimerHandle Time;
private:
bool LoadUrl();
void SetUrl();
FString Tileseturl;
FString RasterOverlayurl;
FString preTileseturl="";
FString preRasterOverlayurl="";
};
2.包含两个需要用到的头文件Cesium3DTileset.h,CesiumTileMapServiceRasterOverlay.h,如果不能包含。可能是你的插件,依赖里没有包含Cesium模块。
#include "Cesium3DTileset.h"
#include "CesiumTileMapServiceRasterOverlay.h"
3.拿到这个TileSet类,需要使用 Actors的数组,通过GetAllActorsOfClass函数(是不是很想蓝图那个)拿到这个世界所有这个类型的类放到这个数组里。
TArray<AActor*> Actors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), ACesium3DTileset::StaticClass(), Actors);
再道数组里拿到第一个Actor类进行Cast转换。
4.通过这个实例类,拿到使用组件通过类型,参数后面记得加::static
CesiumRas = Cast<UCesiumTileMapServiceRasterOverlay>(CesiumTil->GetComponentByClass(UCesiumTileMapServiceRasterOverlay::StaticClass()));
5.读取JSON文件,
JSON数据文件路径,使用UKismetSystemLibrary::GetProjectDirectory() 工程路径。加上你的配置文件路径。
使用FPlatformFileManager静态类里的FileExists来检测文件,FPlatformFileManager::Get().GetPlatformFile().FileExists(*urlPath).
如果存在,再读取。FFileHelper里的LoadFileToString。将文件里的所有字符读到FileStr这个FSring里。
6.准备解析FString 通过TJsonReaderFactory<>创建TJsonReader。 和存储JsonObject的指针 Root;
通过循环 FJsonSerializer::Deserialize解析文件到Root里。Root里拿到每个键对应的值,赋值到变量里。也就是两个url。
//JSON数据文件路径
FString urlPath = UKismetSystemLibrary::GetProjectDirectory() + "CesiumUrl.Json";
FString FileStr;
//获取文件
if (!FPlatformFileManager::Get().GetPlatformFile().FileExists(*urlPath))
{
UE_LOG(LogTemp, Error, TEXT("%s not exist"), *urlPath);
return false;
}
//读取文件到字符串
FFileHelper::LoadFileToString(FileStr, *urlPath);
TSharedRef< TJsonReader<> > Reader = TJsonReaderFactory<>::Create(FileStr);
TSharedPtr<FJsonObject> Root;
//解析文件
if (FJsonSerializer::Deserialize(Reader, Root))
{
if (Root->HasField(TEXT("Tileseturl")))
{
Tileseturl = Root->GetStringField(TEXT("Tileseturl"));
RasterOverlayurl = Root->GetStringField(TEXT("TileMapServiceRasterOverlayurl"));
if (Tileseturl.Equals(preTileseturl) && RasterOverlayurl.Equals(preRasterOverlayurl))
{
return false;
}
else
{
preTileseturl = Tileseturl;
preRasterOverlayurl = RasterOverlayurl;
return true;
}
}
}
else
{
return false;
}
return true;
7.设置url,在将才指针拿到两个实例的情况下,设置url函数。Tile记得刷新,不然会无法及时加载地形。本人在项目中是定时器刷新的。
//获得第一个Cesium3DTileset
TArray<AActor*> Actors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), ACesium3DTileset::StaticClass(), Actors);
//获取和设置两个组件的 url
if (Actors.Num() != 0)
{
CesiumTil = Cast<ACesium3DTileset>(Actors[0]);
if (CesiumTil != nullptr )
{
CesiumTil->SetUrl(Tileseturl); //
CesiumRas = Cast<UCesiumTileMapServiceRasterOverlay>(CesiumTil->GetComponentByClass(UCesiumTileMapServiceRasterOverlay::StaticClass()));
CesiumRas->Url = RasterOverlayurl;
CesiumTil->RefreshTileset();
}
}