콘텐츠로 이동

UE5 Geometry Script — 런타임 메쉬 생성

Geometry Script는 UE5.0+에서 제공하는 프로시저럴 메쉬 생성/수정 플러그인입니다. 기존 ProceduralMeshComponent보다 훨씬 강력한 불리언 연산(CSG), UV 자동 생성, 메쉬 단순화, 콜리전 생성 기능을 Blueprint와 C++ 모두에서 사용할 수 있습니다.


Edit > Plugins > Geometry Script → 활성화
Build.cs:
PublicDependencyModuleNames.AddRange(new[]
{
"GeometryScript",
"GeometryCore",
"DynamicMesh",
});

#include "GeometryScript/MeshPrimitiveFunctions.h"
#include "GeometryScript/MeshBasicEditFunctions.h"
#include "GeometryScript/MeshNormalsFunctions.h"
#include "GeometryScript/MeshUVFunctions.h"
#include "DynamicMesh/DynamicMesh3.h"
#include "Components/DynamicMeshComponent.h"
UCLASS()
class AProceduralBuilding : public AActor
{
GENERATED_BODY()
UPROPERTY(VisibleAnywhere)
UDynamicMeshComponent* MeshComp;
public:
AProceduralBuilding()
{
MeshComp = CreateDefaultSubobject<UDynamicMeshComponent>(
TEXT("DynamicMesh"));
SetRootComponent(MeshComp);
}
void GenerateBuilding(float Width, float Depth, float Height)
{
UDynamicMesh* DynMesh = MeshComp->GetDynamicMesh();
DynMesh->Reset();
FGeometryScriptPrimitiveOptions Options;
// 기본 박스 생성
UGeometryScriptLibrary_MeshPrimitiveFunctions::AppendBox(
DynMesh,
Options,
FTransform::Identity,
Width, Depth, Height,
/*WidthSubdivisions=*/ 1,
/*DepthSubdivisions=*/ 1,
/*HeightSubdivisions=*/ 4);
// 노멀 재계산
FGeometryScriptCalculateNormalsOptions NormalOptions;
UGeometryScriptLibrary_MeshNormalsFunctions::RecomputeNormals(
DynMesh, NormalOptions);
// UV 자동 생성 (박스 프로젝션)
FGeometryScriptMeshBevelOptions UVOptions;
UGeometryScriptLibrary_MeshUVFunctions::AutoGenerateXAtlasMeshUVs(
DynMesh, 0, FGeometryScriptXAtlasOptions{});
// 콜리전 생성
MeshComp->UpdateCollision();
}
};

#include "GeometryScript/MeshBooleanFunctions.h"
void AProceduralBuilding::AddWindows(UDynamicMesh* BuildingMesh)
{
// 창문 커터 메쉬 생성
UDynamicMesh* CutterMesh = NewObject<UDynamicMesh>(this);
FGeometryScriptPrimitiveOptions Options;
// 각 층마다 창문 커터 박스 추가
for (int Floor = 0; Floor < 4; Floor++)
for (int Side = 0; Side < 3; Side++)
{
float WinX = -150.f + Side * 100.f;
float WinZ = 50.f + Floor * 250.f;
FTransform WinTransform(
FRotator::ZeroRotator,
FVector(0.f, WinX, WinZ));
UGeometryScriptLibrary_MeshPrimitiveFunctions::AppendBox(
CutterMesh, Options, WinTransform,
/*Width=*/ 10.f, // 관통 두께
/*Depth=*/ 60.f,
/*Height=*/80.f);
}
// 불리언 빼기: 건물 - 창문 커터
FGeometryScriptMeshBooleanOptions BoolOptions;
UGeometryScriptLibrary_MeshBooleanFunctions::ApplyMeshBoolean(
BuildingMesh,
FTransform::Identity,
CutterMesh,
FTransform::Identity,
EGeometryScriptBooleanOperation::Subtract,
BoolOptions);
}

#include "GeometryScript/MeshQueryFunctions.h"
#include "GeometryScript/MeshBasicEditFunctions.h"
// 높이맵 기반 지형 변형
void AProceduralTerrain::ApplyHeightmap(
UDynamicMesh* Mesh,
UCurveFloat* HeightCurve)
{
// 모든 버텍스 순회
FGeometryScriptIndexList VertexIDs;
UGeometryScriptLibrary_MeshQueryFunctions::GetAllVertexIDs(
Mesh, VertexIDs);
bool bHasErrors = false;
for (int32 VID : VertexIDs.List.Get())
{
FVector Pos;
UGeometryScriptLibrary_MeshQueryFunctions::GetVertexPosition(
Mesh, VID, Pos, bHasErrors);
// 높이 커브 적용
float NormX = (Pos.X + 500.f) / 1000.f;
float NormY = (Pos.Y + 500.f) / 1000.f;
float Height = HeightCurve->GetFloatValue(
FVector2D(NormX, NormY).Size()) * 200.f;
Pos.Z = Height;
UGeometryScriptLibrary_MeshBasicEditFunctions::SetVertexPosition(
Mesh, VID, Pos, bHasErrors);
}
// 노멀 재계산
FGeometryScriptCalculateNormalsOptions NormalOpts;
UGeometryScriptLibrary_MeshNormalsFunctions::RecomputeNormals(
Mesh, NormalOpts);
}

#include "GeometryScript/MeshSimplifyFunctions.h"
void SimplifyForLOD(UDynamicMesh* Mesh, float TargetRatio)
{
FGeometryScriptSimplifyMeshOptions Options;
Options.Method = EGeometryScriptRemoveMeshSimplificationType::AttributeAware;
Options.TargetPercentage = TargetRatio; // 0.0 ~ 1.0
Options.bDiscardAttributes = false;
UGeometryScriptLibrary_MeshSimplifyFunctions::ApplySimplifyToTriangleCount(
Mesh, Options,
/*TargetTriangleCount=*/ 1000);
}

DynamicMeshActor를 씬에 배치:
- DynamicMeshComponent 포함
Construction Script에서:
1. Get Dynamic Mesh
2. Geometry Script > Primitives > Append Box/Sphere/Cylinder
3. Geometry Script > Normals > Recompute Normals
4. Geometry Script > UV > Auto Generate Box UV
5. Update Collision
이벤트에서 파라미터 변경 → 메쉬 재생성

7. PCG(Procedural Content Generation)와 연동

섹션 제목: “7. PCG(Procedural Content Generation)와 연동”
// PCG 포인트 데이터 → Geometry Script 메쉬 배치
// PCG Graph에서:
// - Spawn Static Mesh At Points 대신
// - Execute Custom C++ (Geometry Script 메쉬 생성)
// → 동적으로 변형된 메쉬를 각 지점에 배치 가능
void AProceduralProp::GenerateFromPCGPoint(
const FPCGPoint& Point)
{
float Scale = Point.Transform.GetScale3D().X;
float Height = FMath::RandRange(200.f, 500.f) * Scale;
GenerateBuilding(100.f * Scale, 100.f * Scale, Height);
SetActorTransform(Point.Transform);
}

Geometry Script는 CSG 불리언 연산으로 복잡한 프로시저럴 건축물을, 버텍스 이동으로 지형 변형을 구현하는 데 탁월합니다. UDynamicMeshComponent를 사용하면 런타임 메쉬 업데이트가 가능하고, 완성된 메쉬는 UpdateCollision()으로 물리 콜리전을 자동 생성하세요. PCG와 결합하면 규칙 기반 월드 생성에 변형 메쉬를 대량 배치할 수 있습니다.