一.总体思路
首先使用管理者获得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 propertiesAUrlManager();protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public: // Called every framevirtual 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();}
}