When I spawn an instance of my TerrainGenerator (by dragging from content browser into scene) It spawns the mesh just fine and it shows the material I set programmatically as the set material. However, the material isn’t being displayed on the mesh. If I manually change the material to a different one, and then back to the original it displays fine. I’ve tried placing the setMaterial in a bunch of different functions to no avail. Code included below the images.
TerrainGenerator.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "ProceduralMeshComponent.h"
#include "GameFramework/Actor.h"
#include "TerrainGenerator.generated.h"
UCLASS()
class GENERATIONS_API ATerrainGenerator : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ATerrainGenerator();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
virtual void PostInitializeComponents() override;
void OnConstruction(const FTransform& Transform) override;
void PostActorCreated();
void PostLoad();
void CreateTriangle();
private:
UPROPERTY(VisibleAnywhere)
UProceduralMeshComponent* mesh;
UPROPERTY(EditAnywhere, Category = "Materials")
UMaterial* material;
};
TerrainGenerator.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "TerrainGenerator.h"
// Sets default values
ATerrainGenerator::ATerrainGenerator()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = false;
mesh = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("GeneratedMesh"));
RootComponent = mesh;
// New in UE 4.17, multi-threaded PhysX cooking.
mesh->bUseAsyncCooking = true;
material = CreateDefaultSubobject<UMaterial>(TEXT("Material'/Game/StarterContent/Materials/M_Ground_Grass.M_Ground_Grass'"));
mesh->SetMaterial(0, material);
}
void ATerrainGenerator::OnConstruction(const FTransform& Transform)
{
Super::OnConstruction(Transform);
mesh->SetMaterial(0, material);
}
void ATerrainGenerator::PostInitializeComponents()
{
Super::PostInitializeComponents();
mesh->SetMaterial(0, material);
}
// Called when the game starts or when spawned
void ATerrainGenerator::BeginPlay()
{
Super::BeginPlay();
mesh->SetMaterial(0, material);
}
// Called every frame
void ATerrainGenerator::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ATerrainGenerator::PostActorCreated()
{
Super::PostActorCreated();
CreateTriangle();
mesh->SetMaterial(0, material);
}
// This is called when actor is already in level and map is opened
void ATerrainGenerator::PostLoad()
{
Super::PostLoad();
CreateTriangle();
mesh->SetMaterial(0, material);
}
void ATerrainGenerator::CreateTriangle()
{
int size = 100;
int scale = 100;
TArray<FVector> vertices;
TArray<FVector2D> UV0;
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
vertices.Add(FVector(x* scale, y* scale, 0));
//texture coordinates
UV0.Add(FVector2D(x, y));
}
}
TArray<int32> Triangles;
for (int y = 0; y < size-1; y++) {
for (int x = 0; x < size-1; x++) {
//triangulation
Triangles.Add((y*size)+x);//3
Triangles.Add((y + 1) * size + x);//1
Triangles.Add((y+1)*size + 1 + x);//2
Triangles.Add((y * size) + x);//3
Triangles.Add((y + 1) * size + 1 + x);//2
Triangles.Add((y*size) + 1 + x);//4
}
}
TArray<FVector> normals;
TArray<FProcMeshTangent> tangents;
TArray<FLinearColor> vertexColors;
for (int i = 0; i < size * size; i++) {
normals.Add(FVector(0, 0, 1));
tangents.Add(FProcMeshTangent(0, 1, 0));
vertexColors.Add(FLinearColor(1, 0, 0, 1.0));
}
mesh->CreateMeshSection_LinearColor(0, vertices, Triangles, normals, UV0, vertexColors, tangents, true);
// Enable collision data
mesh->ContainsPhysicsTriMeshData(true);
mesh->SetMaterial(0, material);
UE_LOG(LogTemp, Warning, TEXT("Hello World"));
}