Skip to main content

Runtime Mask Access

Errant Biomes mask data can be accessed in runtime allowing you to drive your game logic by your world metadata.

Our subsystem will handle optimal streaming and caching of the data, leaving you with a simple performant interface for access.

Examples of use cases include:

  • Playing audio based on player location in a biome.
  • Limiting player allow behaviour based on nearby enviroment type.
  • Controlling player hazards like area temperature with same data that is then used to generate enviroment.

Mask Setup

For mask to be available in runtime the Is Editor Only property needs to be set to false(unchecked).

editor only unckeched

Custom Material Mask

This feature composes well with Custom Material Masks.

Custom material mask can be used for offline calculation/preperation of runtime accesed data for improved performance.

For example: Take a mask used to indicate water, calculate expanded, blurred area of that mask for better transitions and elimination of the need for sampling over a larger area in runtime.

Runtime Access

Currently we provide only C++ interface. Blueprint API will be added later.

Access to the data is done through the UBiomesMaskWorldSubsystem, mostly through the SampleMask method.

The subsystem will manage streaming and caching data from masks.

Code Example

Provided here is an example implementation of a simple actor that samples mask under its location in runtime.

// BiomesSamplerTest.h

#pragma once

#include "CoreMinimal.h"

#include "BiomesMaskAsset.h"
#include "BiomesMaskWorldSubsystem.h"
#include "Components/StaticMeshComponent.h"
#include "Engine/World.h"
#include "GameFramework/Actor.h"

#include "BiomesSamplerTest.generated.h"

UCLASS()
class CURRENT_API ABiomesSamplerTest : public AActor
{
GENERATED_BODY()

public:
ABiomesSamplerTest()
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = true;
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));

auto* MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
MeshComponent->SetStaticMesh(LoadObject<UStaticMesh>(nullptr, TEXT("StaticMesh'/Engine/BasicShapes/Cube.Cube'")));
MeshComponent->SetupAttachment(RootComponent);
}

virtual void Tick(float DeltaTime) override
{
if (!GetWorld() || !MaskAsset)
{
return;
}

UBiomesMaskWorldSubsystem* Subsystem = GetWorld()->GetSubsystem<UBiomesMaskWorldSubsystem>();
const float Value = Subsystem->SampleMask(*MaskAsset, FVector2D(GetActorLocation())).Get(FFloat16::MaxF16Float);

UE_LOG(LogTemp, Warning, TEXT("Sampled value: %f"), Value);
}

UPROPERTY(EditAnywhere, Category = "Test")
TObjectPtr<UBiomesMaskAsset> MaskAsset;
};