Knowledge Base: Runtime Landscape Editing

Runtime Landscape Editing
Article written by Ryan B.
Information on editing landscapes during runtime is quite commonly requested, and this article aims to share insight into what would be involved in achieving this wi…

https://dev.epicgames.com/community/learning/knowledge-base/vzrZ/unreal-engine-runtime-landscape-editing

23 Likes

In the time since this was first posted, has anyone implemented this?

Its probably completely pointless.

There is nothing in engine as badly designed as the landacape system.
Working with it given all its limitations when a properly made runtime procedural mesh does everything you need and a lot more is essentially a waste of anyone’s time.

Not to mention the fun fact that even in its current baked state the cost of landscapes is far too high compared to any competitor engine you care to try…
Epic just loves to kick this particular dead horse around instead of designing a more up to date best practice following system.
Thats actually how we ended up with “edit layers” in the first place…

If you are serious about your project happening, just look for pre-made tools including but not limited to using off the shelf Voxel plugins to achieve runtime editing…

2 Likes

luoxz implements complete runtime terrain landscape editing

Since nobody ever helps here with this question, I’l do. I managed to make procedural landscape in multiple ways (albeit took me a month of looking throuhg plugins, experimenting, even trying to make my own landscape solution)
.

  1. load from texture using: LandscapeTest->LandscapeComponents[i]->SetHeightmap(HeightMap);
  2. load from rendertexture using:
    ||TArray SurfData;|
    |—|—|
    ||auto RenderTarget = RTHeightMap->GameThread_GetRenderTargetResource();|
    ||RenderTarget->ReadPixels(SurfData);|
  3. just writing heights to FColor:for (int x = 0; x < 256; x++)
    {
    for (int y = 0; y < 256; y++)
    {
    uint8 height = x;
    SurfData.Add(FColor(height, height, height, height));
    }
    }

Additionally need to call some function to trigger the redraw and recreate collisions:

for (int i = 0; i < LandscapeTest->LandscapeComponents.Num(); i++)
{
	LandscapeTest->LandscapeComponents[i]->MarkRenderStateDirty();

	LandscapeTest->LandscapeComponents[i]->InitHeightmapData(SurfData, true);

	// NOTE: crash if edit layers is on.
	// NOTE: crash cuz of no mips.
	// NOTE: srgb collision offset?
	//LandscapeTest->LandscapeComponents[i]->SetHeightmap(HeightMap);
	LandscapeTest->LandscapeComponents[i]->RequestHeightmapUpdate(true, true);

	LandscapeTest->LandscapeComponents[i]->UpdateCachedBounds(true);
	LandscapeTest->LandscapeComponents[i]->PostLoad();
}

//for (int i = 0; i < LandscapeTest->CollisionComponents.Num(); i++)
//	LandscapeTest->CollisionComponents[i]->RecreateCollision();

LandscapeTest->RecreateCollisionComponents();
2 Likes

Thank you for the insight @avol
i believe the whole endeavor would be impossible with blueprints only, right?

@avol
Sure. And how long does something other than a PC take to re-create collision component?

Theres a reason no one does this with the default landacape - aside from the fact the system itself is bad.
That’s the possible size of it.

You have to modify everything - or even just a single component when you do it right which you aren’t btw - and each component is far too much for most systems to handle at runtime along with the rest of your game’s procesing.

You may be able to improve a bit by getting the difference between the original and the new map, resolving which compnents need to be updated, and manually updating collision just for those.

It may work in testing on a single landscape setup - and it could be a decent idea for some stuff - but its a hitch along system rather than a gameplay element, which is what people generally want.

In other words, you can run the code but you will end up overloading the CPU/GPU if you constantly update every frame, which is what players usually intend to do with actions while sculpting.

Dont get me wrong, its not horribly bad (the editor does it, right? Hitching like crazy most of the time but it does it) performance for the task at hand - but if you also start adding movement of foliage and re-drawing of grass etc to the equation like you probably need to, you end up lagging dreadly behind.

On the other hand, making something with an off the shelf voxel system designed specifically for gameplay goes around most of that - and also allows creating holes and 3d representations.

@Aphexx100
At the bare minimum youd need to be able to know how to throw his shared code up in a blueprint class, make a blueprint callable function, and expose the correct textures to the function so that you can feed them in along with whater exec pins need to run the code.

Its not that hard really. But the performance of it is going to be very limiting, not sure its worth anyone’s time.

What would be worth people’s time?
Procedural mesh component.
If you have to bark up any tree at all, that one would probably be the best.

You can then choose to create an analytical mesh based on pixel heights rather than a hard set “one verxtex each unit set” measure… for one…

Yes my big mistake, posted my response too quickly before doing more testing :slight_smile:
Aside from performance (which in my case I didn’t care about, because I only wanted to generate maps with some loading screen) it’s also not compiling to runtime. And has some other issues which make it unusable.

No big deal, and too bad.

Though not viable for everyone, it would at least have been an option for some very select situations.

If you are still at it, I suggest making a fully custom system.

Because in a procedural mesh the positions of the vertex are known (x/y being constant) you can save data by just passing in Z.

The tris order is always
Up Left
Down Left
Down Right

Up Right is ways = to Up left, and down left is always the same as down right when you move to the next instance.
As such, a comma separated list of Z values can easily be enough to generate the whole landscape with Zilch in terms of storage cost.
(Should be called a triangle strip system if i remeber correctly).

If you really want to gut things to nothing, the other data stored is the normal.
You can easily represent it with 2 int16 values.
(Dont think the engine will know what to do with it, but ao long as your math sets the normal to what it should be then the engine is only aware of the normal. Not of how you store and use the data for generation - again, the issue here is generation and the sheer amount of data it requires).

The benefit of making somerhing like this would basically be the ability to stream in an endless line of vertex to continually generate new strips…

Onviosuly you srill have a bottleneck on rendering/amount of tris.

So you need to come up with some sort of aggregation or tiling system.

Unlike Epic’s mess, which does it with some low level mipping (deletes your data at a diatance on a /2 scale with each LOD)

I would suggest finding different and Analytical approaches.

Just like you can simplify a ton of different ways, having a 0 in the data stream for any vertex Z that is below a height requirement treshold would probably net some interesting simplification results (but still use all the verts).
Removing the verts analytically that’s where the real magic happens…

I ended up with using shader world plugin from marketplace. I do need very detailed terrain mesh and lods for my snow system to work properly(reserving WPO for that) and making procedural landscape with procedural mesh component is just too slow and requires too much work to make proper lods.

Max D’s plugin right? If so, congrats. Show off a demo video of the results (if you feel like it). :wink: