Hello Everyone,
I am trying to make a landscape actor, at this stage I just want a large flat landscape that I can later displace using noise calculations fed into a utexture2d.
Right now this is my header:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Landscape.h"
#include "LandscapeComponent.h"
#include "FlatLandscapeActor.generated.h"
UCLASS()
class HOUSE_OF_PALAIOLOGOS_API AFlatLandscapeActor : public AActor
{
GENERATED_BODY()
public:
AFlatLandscapeActor();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Landscape")
int32 Width;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Landscape")
int32 Height;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Landscape")
float Scale;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Landscape")
int32 ComponentSizeQuads;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Landscape")
int32 NumSubsections;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Landscape")
int32 SubsectionSizeQuads;
UPROPERTY()
uint16 FlatHeight;
private:
UPROPERTY()
ALandscape* Landscape;
UPROPERTY()
ULandscapeComponent* NewLandscapeComponent;
UPROPERTY()
TArray<uint16> HeightmapData;
void InitializeLandscape();
};
This is my cpp:
#include "FlatLandscapeActor.h"
#include "LandscapeEdit.h"
#include "Engine/World.h"
AFlatLandscapeActor::AFlatLandscapeActor()
{
PrimaryActorTick.bCanEverTick = true;
// Set default values
Width = 128;
Height = 128;
Scale = 100.0f;
ComponentSizeQuads = 63;
NumSubsections = 1;
SubsectionSizeQuads = ComponentSizeQuads;
FlatHeight = 32768; // Midpoint for flat terrain
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
}
void AFlatLandscapeActor::BeginPlay()
{
Super::BeginPlay();
InitializeLandscape();
}
void AFlatLandscapeActor::InitializeLandscape()
{
if (!GetWorld())
{
UE_LOG(LogTemp, Error, TEXT("World is null."));
return;
}
// Create a Landscape Actor
Landscape = GetWorld()->SpawnActor<ALandscape>(ALandscape::StaticClass());
if (!Landscape)
{
UE_LOG(LogTemp, Error, TEXT("Failed to create Landscape Actor"));
return;
}
// Generate a new GUID if it's not set
if (!Landscape->GetLandscapeGuid().IsValid())
{
Landscape->GetLandscapeGuid() = FGuid::NewGuid();
UE_LOG(LogTemp, Warning, TEXT("Generated new LandscapeGuid: %s"), *Landscape->GetLandscapeGuid().ToString());
}
Landscape->SetActorLocation(GetActorLocation());
Landscape->SetActorScale3D(FVector(Scale, Scale, 1.0f));
Landscape->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
// Initialize the landscape's properties
Landscape->ComponentSizeQuads = ComponentSizeQuads;
Landscape->SubsectionSizeQuads = SubsectionSizeQuads;
Landscape->NumSubsections = NumSubsections;
// Ensure the Landscape Info is created
Landscape->CreateLandscapeInfo();
// Initialize Heightmap data (flat terrain)
HeightmapData.Init(FlatHeight, Width * Height);
if (NumSubsections * SubsectionSizeQuads != ComponentSizeQuads)
{
UE_LOG(LogTemp, Error, TEXT("Invalid landscape dimensions"));
return;
}
// Create Landscape Component
NewLandscapeComponent = NewObject<ULandscapeComponent>(Landscape);
if (!NewLandscapeComponent)
{
UE_LOG(LogTemp, Error, TEXT("Failed to create Landscape Component"));
return;
}
NewLandscapeComponent->SetSectionBase(FIntPoint(0, 0));
NewLandscapeComponent->SetupAttachment(Landscape->GetRootComponent());
// Initialize the landscape component with appropriate parameters
NewLandscapeComponent->Init(0, 0, ComponentSizeQuads, NumSubsections, SubsectionSizeQuads);
// Register the component
NewLandscapeComponent->RegisterComponent();
// Ensure that the Landscape Info is valid
ULandscapeInfo* LandscapeInfo = Landscape->GetLandscapeInfo();
if (!LandscapeInfo)
{
UE_LOG(LogTemp, Error, TEXT("Failed to get Landscape Info"));
return;
}
// Double-check LandscapeGuid
if (!Landscape->GetLandscapeGuid().IsValid())
{
UE_LOG(LogTemp, Error, TEXT("LandscapeGuid is still invalid after attempted generation."));
return;
}
// Access the heightmap data using FLandscapeEditDataInterface
FLandscapeEditDataInterface LandscapeEdit(LandscapeInfo);
LandscapeEdit.SetHeightData(0, 0, Width - 1, Height - 1, HeightmapData.GetData(), Width, true, nullptr, nullptr, nullptr, true, nullptr, nullptr, true, true, true);
// Add component to the landscape
Landscape->LandscapeComponents.Add(NewLandscapeComponent);
// Update the component's bounds
NewLandscapeComponent->UpdateBounds();
// Register the actor with Landscape Info
LandscapeInfo->RegisterActor(Landscape, true);
UE_LOG(LogTemp, Log, TEXT("Landscape initialization completed successfully."));
}
void AFlatLandscapeActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
It keeps crashing when I click play, any help would be greately appreciated.