Leveraging PCG for Building and City Creation | Unreal Fest Bali 2025
By Unreal Engine
Summary
## Key takeaways - **Procedural Thinking for Environment Creation**: Procedural thinking involves identifying patterns and applying similar operations to solve complex environment creation tasks, which is fundamental to leveraging tools like PCG for dynamic city and building generation. [01:46], [01:50] - **PCG Framework for Scalable Cities**: The Procedural Content Generation (PCG) framework in Unreal Engine 5 enables the automation of complex environment creation, allowing developers to build scalable and immersive cities efficiently by managing modular assets and flexible grammar rules. [02:06], [02:11] - **Modular Asset Design for PCG**: Designing modular assets in software like Plasticity and then processing them in Houdini for UV naming and FBX packing is crucial for their effective use within the PCG framework, ensuring they integrate correctly with materials. [03:04], [03:10] - **Grammar for Pattern-Based Generation**: Grammar in PCG provides a structured way to define patterns for elements like walls and floors, recently added in Unreal Engine 5.5, simplifying controls for artists through buttons and presets. [03:23], [03:30] - **Dynamic Building Generation with Attributes**: By adding attributes like 'shrink direction' and 'shrink strength' to floor points, and utilizing noise and rounding nodes, buildings can be procedurally generated with varied floor sizes and shapes. [06:37], [06:45] - **Automated Wall and Corner Module Placement**: Walls and corners can be procedurally generated by splitting floors into cubes, moving them, and using subtraction operations, which then react dynamically to building size changes. [10:24], [11:14]
Topics Covered
- Why procedural results should be quantized, not random.
- How can props intelligently adapt to any surface?
- Create smart assets aware of their environment.
- How nested procedural tools enable scale and control.
- How one material can create infinite procedural variations.
Full Transcript
All right, thank you so much for coming.
My name is Daniel Mo. I'm a technical
artist at virtuals and I like to do
portal tools and creating games.
Today we're going to talk about PCG and
buildings. We'll take a short look at
the results and create a similar tool
set. So, first a quick video showing the
results. Heat. Heat.
[Music]
Heat. Heat.
[Music]
All right. So, let's take a closer look
at the buildings tool feature. In this
talk, we're going to mostly focus on
this one, the buildings. We're going to
change the size, floors, and props here.
And we're going to sort of learn
procedural thinking. How can we spot
patterns and use similar operations to
solve them? Here are some buildings
variations. So, we randomize here the
the props, the floors, and here are some
variations
here. Next is the city tool.
We will move the city around. The tool
is showing a preview mode by default. We
can change parameters such as seed and
size and control the results by setting
the minimum and maximum floors for
example. So we kind of control the
ranges. Eventually we will generate the
actual buildings. So it's kind of a tool
that contains the building tool.
Let's view the materials functionality.
The material itself is very basic. No
textures. I'm going to share a few
tricks. First, how to create the mask
that we did and add the variations for
actors or instances. So, we can do both
of them. Here we change the basic
material properties, color, metallic,
roughness.
Modules.
The modules were designed in plasticity.
In Udini, we've done UV naming and
packed in FBX. Here you can see it in
with the material we went over earlier.
Grammar is a fancy way to describe
patterns in the context of building. We
will set walls and floors patterns. It
was added recently in Unreal 5.5.
This shows a button for artists to
interact with predefined wall patterns.
The idea is to kind of simplify the
controls wherever we can, either by
using buttons, presets, or anything that
is simple to do.
We will now set up the project.
We would prioritize logic over just
connecting nodes or doing a step-by-step
tutorial. I hope to deliver value for
both beginners and advanced users.
building tool. So, let's set it up.
Start by enable building the PCG plugin,
edit plugins PCG, and just enable it.
To create assets, simply right click in
your content browser, click the
blueprint class, and choose actor, name
it, and type PCG to do the same.
Open the blueprint.
Add a PCG component and link the PCG
asset to it.
Our goal now is to control the size and
the amount of floors of the building.
Open your blueprint and add three
parameters. Floors, size X, and size Y.
They will be whole numbers, integers.
We are now going to open our newly
created PCG class. We're going to use
the get actor property node and just
read the variables by specifying its
name. We basically read it from the
blueprints.
Next, we're going to use the create
point grid node. It is used for floors
and the size of the building. Here we
basically create one point for floor per
floor.
With this node, we get the power to sort
of precisely spawn points. It can be a
2D grid like the name of the node. And
it can also be a 3D one or a point above
another point which is just perfect for
floors. Here,
this is how your graph should look like
so far. You will notice a few more
nodes. I added some math nodes such as
converting meters to cm. I'm not going
to focus on them a lot today.
We're going to keep them pretty simple.
Add subtract multiply flow and
modulo.
Here are all flows. I added a gap here
between for visibility. But if you
choose your if you select your create
grid node and press D for debug, they
should appear on top of each other.
Sometimes some floors can be bigger or
smaller than others. We can kind of use
that fact to generate more interesting
buildings. So, let's mess a little bit
with the floor size.
Since every point or cube, which I will
use interchangeably here, can contain
attributes. We're going to add an
attribute for each floor. The first one
will be shrink direction. Add the noise
and round nodes. The noise will generate
a 0ero to one values. The round will
ensure that we get either zero or one.
If the attribute of that flow is zero,
we're going to shrink it from the front.
If it's one, we will shrink it from the
back.
But direction is not really enough. How
strongly do we want to shrink its flow?
40% 60%.
Another attribute can help us answer
this question.
It will be shrink strength. It's going
to be the same idea. 0 to one noise, but
this time we're not really going to use
round at all. So a zero would mean no
shrink and 04.5 would mean 50% shrink.
We can also spice it up a little bit
with some height gradient. So we can
control that lower floors will shrink
more or less depending on what you want.
One problem with shrinking floors is
that we might get some small deviations.
Usually it will look bad and
unintentional.
To fix that, we're going to sort of step
our shrink allowing only few specific
shrink shrink values.
If we allow three values 0, 50, and 100,
a 60% shrink will become 50%. And 10
will become zero, meaning we don't
shrink.
Six to eight steps work well for me, but
honestly, meters per step would be more
reliable.
Before we continue, let's create sort of
two mini tools. We're going to use them
a lot.
This one splits any cube to smaller
cubes. It will measure the size of the
cube and break it down accordingly.
It means that this cube, let's say a 3x3
m, will be sliced to 27 smaller cubes.
Next, we're going to normalize float.
It's another sort of subgraph. So let's
say each flow has an attribute 0 is zero
and one is one up until floor 9. We can
find the maximum and minimum attributes
of those flows and compress them into 0
to one range. So floor zero stays at
zero. Floor 9 now becomes one and the
rest of the floors are somewhere in
between.
So far we just played with attributes.
We didn't really we didn't really do any
shrinking. So let's do it by looping
over each floor.
In the shrink loop, each floor will be
converted to 1 m cubes with the mini
tool we created earlier. The position of
each row of cubes will be normalized
between zero and one.
Filter any row with lower density than
the floor shrink strength. The second
floor is shrinking for 40% from the
front. We just delete values below gray.
This is our graph so far. Most of the
extra stuff that I didn't mention are
just extra controls for the user. For
example, disable shrinking altogether or
allow one direction.
And there it is. We shrank the floors.
They now adapt to the size of the
building. And we've added control for
seed, direction, strength, and steps.
But first, let's do some walls and
corners. We can spawn them. We're going
to start by splitting the floors into
first floor and other floors.
The input of the node will be floors
after we shrink them. The output is
going to be walls as corners. Walls and
corners as modules.
We are going to work with a period of 1
m cubes. This time we're using a 2D
grid. No need for a three-dimensional
one. We will move them around and just
check if they overlap. That's about it.
So to create point grid,
uh yeah, use the create point grid
again. This time we do not want many
cubes stucked vertically. Just one
there.
For the wall, duplicate the cube grid.
We're going to move it 1 m to any side,
either X or Y, and subtract from the
original. Now the wall is just ready as
1 m cubes.
For the corner, it's pretty much the
same idea. We just do it twice. We take
the wall, duplicate it again, and
subtract. So, we now get a corner piece.
Here's our tool so far. The corners here
are blue and the walls are made from 1 m
cubes. It reacts to size changes.
Now we're going to sort of split each
wall or rather combine those modules
since all of them are 1 m and sometimes
we want like 4 m pieces. We we we will
do it in the same in the next slide.
So the logic of the wall split is large
to small. We try here 4 m until we fail,
then 2 m until we fail again, and then
we fall back to 1 m, which we know we
always have.
The cuff itself is looking scary, but
it's pretty much the same row duplicated
four times. So let's dive into one row
first. To avoid errors, we will figure
out if there are any points left to fit
walls into. So keep the first point
using attribute filter. Add some
attributes. Uh we will set it to true
and then input it to the branch node. If
there are no points, the attribute the
branch node will interpret that as false
as it didn't really add a true attribute
here. And then it will effectively stop
the flow of the graph outputting to a.
If we do find points to fill wall to fit
walls into filter the ones that fit
using attribute reduce modulo and filter
by range. In this part we get the sort
of remainder the part that won't fit and
we can final it into the next small
module smaller model test below.
Lastly, we divide by the index.
We divide the index by the module size,
floor, and partition.
So, let's take a look at like a 2 m
example. Indices are usually zero and
one. We're going to divide them by two
for 2 m. This will yield 0 and 0.5.
Flowing it will give us zero for both 1
m cubes. So now the indices are 0 0 1 1
22.
We're going to partition the cubes
according to their new index. Basically
grouping each one each cube that are the
same index.
And this is our segmented walls. They
are not 1 m cubes anymore. They are kind
of combined cubes at different sizes
that we wanted.
We are now ready to actually spawn some
actual meshes. Filter the points
according to their type and dimensions
and uh sorry use match and set
attributes to specify which meshes to
spawn and eventually drop a static mesh
spawner.
But how do we actually specify which
meshes do we want to spawn?
We're going to create a struct a
structure. Open it up and add two
variables. One float for the weight and
one mesh for the mesh. Add it into your
blueprint just as a normal attribute.
Set the defaults.
And eventually go to the PCG building
and read it using the same node that we
did earlier. Get actor property.
Here's our building now with real walls
and corners.
You're going to notice some doors here.
Let's see how it was done.
Each wall segment will get a random
noise. The range of the front will be 0
to one. The sides will be zero to 0.5.
We're going to pick a module and just
simply convert it to a door.
It's going to be based on what's the
highest number. So, it will be very
likely that we get some door at the
front and less likely that we get a a
door at the sides.
Here's a zoomed out view of the doors
graph. And here's a video with some
close-ups. We use the building
circumference to determine how many
doors to spawn. We can simply count how
many 1 m cubes we have. And you can look
at it later in the recording to get some
more details.
And here are the doors marked in green.
Here we expose door frequency for this
and seed for the user. For example, I
want a door every 20 m. It will always
spawn one door. So we kind of force it
to spawn a door at the front.
Our graph just became too big for a
simple picture. Here's a video of it
now.
One type of control we want to expose is
SID. It will allow us to kind of
randomize the whole building by just
changing a number or randomize a
specific part of it such as roof pops.
Here's an example of global seed and
individual seeds being added together in
order to sort of determine the final
seed.
And here's another way to do it. I
wanted to stress that mutate seed is
kind of dependent on position.
So we can basically change the seed by
changing a little bit the position of
the building.
This will yield the different seeds if
we move them. And since our calculation
is at water region, it should be
consistent unless we change it.
A common issue is when you kind of move
your PCG graph, but it stays at the same
place at the world center. We can simply
move it to the to the center of the
actor.
We're going to use a new node get actor
data as a single point. This will kind
of give us a point where the actor
centroidid is. And this is where we're
going to keep every to copy everything.
I placed it right before spawning static
meshes. It makes the graph kind of more
stable.
Our building moves now and everybody is
happy.
Let's tackle the most important things
after walls. It will be roofs.
We're going to convert our floors to
cubes once again, but all of them. We're
going to duplicate it and move it
downwards 1 m.
Finally, we're going to just remove the
overlap and we end up with those roof
cubes.
Here we show the graph filtering the
roof locations 1 m cubes. Now, we're
going to just split it into bigger inter
bigger modules.
Let's apply what we learned here uh at
wall segmentation before, but this time
we're going to do it for the roofs. So
we're going from 1D algorithm here to
2D.
We're going to start with large models
4x4 m and then going smaller until we
reach 1 m.
Here we try 2x two. We got to the first
two and then we start failing because
there are just not enough cubes to
satisfy it. So we fall back to one by
one m.
The input of the graph are 1 m roof grid
and the size of the model you would like
to fit. Let's say 4 m or 2 m.
This is how the split graph works. We're
first indexing and then splitting to
valid or invalid modules.
We're going to set the index of each
cube in X and Y. So the cube of the corn
in the corner will be 0 0. the one next
to it will be zero and one.
Here's a more detailed explanation. You
can read it a little bit later, but the
idea is that we just check how many
cubes occupy each segment and then
determine if it's a valid segment or
not. So, with 2x two, we'll require four
cubes.
Now the roof is present adapting to any
changes including the size of the
building or the shrinking settings that
we set.
So far we made a lot of progress floors,
walls, doors and more.
We are now going to basically set dress
our building adding props, pillars and
floors just to generate some areas with
higher details.
So if the previous section was the
tutorial, this is the final boss. We're
going to do wall props.
The idea is to kind of avoid placing
props on open areas such as windows.
We want to avoid areas that stick out
beyond the wall's baseline, too. This is
a common problem, and usually we tackle
that with tugging areas or something
like that, but I wanted a fully potal
solution that kind of adapts to your
model.
So, we're going to scatter some points
on the walls and the props. We're going
to measure the distance of the props to
the walls using those points. If the
average distance in this case is less
than seven cm, the prop is determined as
valid.
For the main loop, we will loop over
each floor. We're going to input the
locations to test, the walls as points,
and the props as points.
And here's the full process.
If the average distance is too big, we
just discard the prop. We just compare
those points and if the distance is too
big, just discard it.
It's going to avoid windows and it also
adapts to changes of the input measures
or walls.
Here's a look inside a graph where we
use the distance node to compare
distances.
After we've done with the distance test,
we apply weights, remove overlap, and
add coverage attribute.
With the final node being a static mesh
spawner
and those are the results. Our props are
not floating. We didn't have to
explicitly indicate where they should
avoid. And it kind of leads to
interesting patterns.
It's also fast.
The wall props are kind of the most
complex part of this tool. For now,
we're going to speed up and focus more
on the logic.
Starting with the corner props, we're
going to duplicate the corners and move
them 1 m outwards. And that's it.
We're doing a very similar thing here.
Move noise normalize coverage and
SID. Nothing new. Here
are the results. We can change the
corner props coverage or change the
modules and their weight. Let's say we
want more of a specific model or we
don't want this module at all.
For the roof for the roof props, we
simply scatter. If we simply scatter
props on each roof, we're going to
encounter overhang like in this example.
To solve it, we are going to measure
each asset and based on its biggest axi,
we scale down the viable spawn
locations. Basically shrinking the roof
according to each asset. It's going to
help us avoid overhang.
This graph shows how to apply the logic.
We are looping over each each asset and
then shrink the floor the roof according
to it.
Here are the results. there's no
overhang and just many possible
variations.
We also rotate it by 90° increments and
make sure that there's no overlap. More
on that later.
For the exterior props, we are now going
to play with the roof cubes and the
walls cubes. We're going to just move
them around and find if they intersect.
The red cubes here are kind of perfect
for us. They're not floating and they're
close to the walls. A common place for
people to play stuff.
Here's a look at a graph. It's the same
nodes, but different outcomes
and the results. Just one more layer of
interesting stuff we've added to it.
For the railing, it's going to be the
same idea, but this time we're going to
play around with walls and corners.
Move both of them upwards and intersect.
By this time, I kind of hope you start
noticing a pattern. We're just moving
cubes and checking for overlap. Nothing
over complicated.
And this is the graph I've added here.
Uh tall pillars too, in between floors.
try to produce that logic. It's kind of
fun.
It starts to feel more grounded now with
the railing seat parameters are now
exposed for both the railing and the
short pillars.
It simply changes the model
for the foundation pillars.
Buildings usually float on uneven
terrain. Adding a foundation pillars can
sort of solve that so they will not
float and look kind of interesting.
We're going to measure the distance from
the go corners to the ground and then
spawn pillars accordingly.
Many things can be done this way.
This is how it looks applied to the
tool. We can apply this idea to many
assets. shoot rays in different
locations and sort of create a library
of smart assets. Assets that are kind of
aware of their environments. The pillars
here just won't spawn if they are not
needed, which leads to nice behavior and
optimized environments.
For the ground floor, duplicate the
bottom cubes, move them around, add them
to the original, and just spawn tiles
later.
We now have the floor. It's possible to
control the size, scale, tiles, and
railing.
This is the ground floor and foundation
pillars graph. It kind of made sense to
place them at the same general area.
And here's the full graph. We went
almost over all of it.
Here
are the full results of the building.
Here we randomize pretty much
everything. I added a random button that
kind of changes all of the variables.
Seed usually can change most of the
stuff, but I wanted to keep the floors
stable. For example, so if the user
wants three floors, he can still change
the seed, but keep the floors. This
boton kind of randomize everything.
Next is the city tool. We're going to go
over it much faster. This is also a
simpler tool than our building.
To create uh first create two assets,
one blueprint, one PCG, just like we
created for the buildings, but this time
for the city.
add some variables. Since we want to
vary the buildings within range, we're
going to use a minimum and maximum
scheme. So, let's say a minimum of one
floor and a maximum of 10 floors.
You see those vector 2D at the bottoms,
which is just two floats, two simple
numbers. We will use it for minimum and
maximum.
So, we're going to start with the same
node, read variables, create point grid,
and this time we are going to move the
points randomly and X and Y. We don't
want them to be a perfect grid.
This is the point grid before we moved
it. We're going to pretty much assign
attributes to each cube. Each cube will
be a building according to its will
spawn a building according to its size
and place.
We're going to randomize the X and Y
size of the buildings. We're copying the
size to scale to get an accurate debug
preview. And we now use the attribute
normalize graph again. It is back, but
this time we don't really normalize it
from the 0 to one. We normalize it to
what the user wants. Accord. So let's
say 0 to nine for the flows.
One issue with our approach is the
overlap here.
To solve that, we can use selfing which
I kind of love.
It removes uh sorry it removes kind of
overlap from everything. It's a really
valuable node.
Next, let's rotate each building by 90°
steps. We're going to use the floor
operation here and just do a few simple
maths to to sort of get it.
Here's our rotated non-over overlapping
buildings. In a full city, we can think
to sort of rotate the buildings toward
the road or do some more interesting
layouts.
We're going to randomize the possible
flows.
I wanted to mention that kind of
real-time feedback and quick iteration
speeds are really valuable.
Every environment can kind of enjoy this
flexibility even just as a blockout
tool.
Why use a cubes for buildings and
neighborhoods where can Well, we can
create a blockout tool. The artist
doesn't have to guess how many floors
the cube is or continuously measure it.
and then center it like on the ground.
So for the shrink strength range, we're
going to randomize this one, too. We're
going to shrink buildings a little bit
less less frequently um if they are
taller.
It kind of makes sense because we want
the taller buildings to not have many
many variations, but on smaller
buildings, we want many interesting
shapes.
This is the guy we're randomizing. How
much do we shrink?
For the props, we're going to use the
distance node. We will spawn less less
props if the buildings are kind of
closer to each other.
This is just a simple experiment, but
you can play with whatever logic you
find interesting.
For the roof pops, we will use regular
attribute noise, resulting in more
frequent coverage variations than the
special noise, which is kind of
consistent in space
for the doors. Nothing complicated here.
It's the same pattern, noise, and
normalize to range. We're just doing it
over and over again in the CD tool or in
many other tools, too.
We're going to alternate between our
wall types large to small that we
created and grammar that we're going to
create later.
So about grammar, as I said, it's
basically like patterns.
It can help us achieve interesting ones
such as alternating between modules or
specifying the start and end module and
end module.
We're going to move the city to the
actor centroidid. It's a really common
operation and we've done it with the
building earlier, but now just for the
city.
Next, we want to kind of determine the
height of each building.
We don't really want it to float, but we
don't want it to sink on uneven
terrains.
To solve that, we're going to convert
our building to one metal cubes at the
base.
We're going to shoot some rays toward
the bottom and then check what is the
highest point that kind of snaps to the
terrain.
Then we're going to copy the height of
the highest no highest cube marked in
red here for the rest of the building.
Convert the base of the building to 1 m
cubes. Once again,
rate to the landscape. Find the highest
cube and copy its height to our
unmodified building. This is the only
attribute we need from here.
And finally, we're going to actually
spawn the buildings. We will do that by
spawning the blueprint actors we created
for the buildings.
So the building blueprint contains a PCG
graph and we're now using like a
blueprint within and the PCG within it.
We're going to override the blueprint
variables and this is why we generated
all of those v variables earlier. It's
going to enable us full control as if we
placed those buildings manually and just
change some parameters.
This is really valuable because after we
generated many buildings, we can come
and just like change one specific
building.
And there's the city PCG graph compared
to our building. It's kind of light.
And there's the result. We move it
around and it adapts to height.
We are changing the seed and the size
and the different ranges we created such
as minimum and maximum flows or minimum
and maximum size.
Eventually, we generate the actual
buildings. I did add here like a preview
mode which is snappy and kind of shows
you how it's going to roughly look. We
can even make the preview preview mode
better by showing the shrinking presets.
So let's view the material setup.
Two simple material uh create two simple
materials. color, roughness, metallic,
the usual.
To alternate the secondary color of some
buildings, drop an actor position and
round node. It's going to generate a
0ero to one uh values for each actor,
which might sound familiar by now.
We're going to add a mask. So, where
would the first and second material be?
The trick here is to calculate the mask
at the default position of the model
before removing it or rotating it.
Expanding on this idea is kind of
interesting.
Blend the material using the mask we
created on the previous slide.
And now we want to kind of add color and
roughness variations to some assets. for
example, AC unit will be nice if some of
them were a bit more dirty or a bit
darker in this example.
So, similar to speed's color variation
node, but here we control the U
saturation and values individually.
The key nodes here will be per instance
random, which gets us a 0 to one value
per piece.
It's the same as the attribute noise we
used in the PCG graph, but this time
we're doing it in materials.
Use the remap node, which is like
attribute normalize, but we kind of
assume a 0ero to one inputs because we
don't actually measure the darkest and
the brightest pixel here.
And one more thing we can do is use RGB
to HSV node which is just just perfect
for variations.
Since we don't want to vary just the red
channel or the green channel, we want to
vary the U or the saturation.
This is the complete graph
and this is the material results. We're
changing parameters such as colors
and we can enable inter actor
variations. So one of those buildings
are gold uh tint and summer is blue or
red
and the per instance variations which
kind of screws the modules
but it's useful for AC units.
For the modules,
I really enjoy plasticity. It helped me
design a huge selection of models. It's
a modeling software using ns similar to
card and things like that. It's
intuitive to use and well designed. So,
if you like hard surface, I really
recommend you checking it out.
Here's a top view of the models. It took
several iterations to come up with the
dimension and kind of make sure
everything fits, but the process is
satisfying.
Here's a top view of the props. Each
cube grid is 1 m, so you kind of get a
scale for fence.
In your DNA, we use to name, UV, and
center the kit. We can also use the DNA
to visualize anomalies like pieces with
many polygons or pieces with holes.
Those are marked in red here. It's very
useful
for grammar.
Grammar, as I said, is a way to sort of
describe patterns. In this example,
we're going to use it for walls and
floors. It's available since 5.5.
Here's the graph.
We're going to start by converting a
cube to a spline. Each flow will have a
sort of base plan for it.
We're going to use the wall extraction
process we did earlier. Everything is
the same, but we just take the corners
and input them into a create spline
node.
So now we get a spline at the base of
each floor. We kind of do it because
grammar expects lines as input.
Starting with the vertical grammar
flows.
What kind of flow pattern do we want? Do
we want one first and one last floor
flow with many middle floors in between?
Or maybe we want one first floor and
then alternate between different assets.
Let's call them middle and last floors
for this example.
To the left, the grammar section was
taken from Epic's example. They have a
really great example in engine.
We force the direction of the spline and
convert the spline to points.
If the right side of the in the right
side of the graph, we will classify each
wall segment and apply different grammar
depending if it's the front, sides or
back.
For the horizontal grammar, it will be
for the walls. I prefer readable naming
over concise. So I chose wall 1 M1 which
is like the first module of the 1 m
dimension walls which is a bit more
accessible than what I usually see like
W1 or W1A. I think it's worth the extra
the extra letters.
Here we load the modules. We do that by
reading the same strat from earlier.
We're going to merge all of the possible
wall modules. We're going to allow scale
for some or all of the modules. Not
allowing scale will kind of fail the the
segmentation process, but the scale
should be really really minor if if your
pieces fit.
Extract mesh info is one more example by
Epic, which kind of finds the dimensions
of each module. Use that. It's really
nice.
This is the actual grammar segmentation.
It's the subdivide node to the left.
All of this the grammar se the grammar
section will be output into this sort of
yeah redirection node. Forgot it exact
name
to easily enable gunner toggle this
parameter. We're using an enum here.
Enums are great because we kind of get a
drop- down menus with selections that
are easy to understand for the users. We
could use a boolean here, but it won't
be as clear as selection, and we will
lose the option to include a few more
options if we want more than two.
The results are the ability to change
grammar in a bit more intuitive way,
either by clicking a button or editing
the strings.
We are now done by the with the project
setup. I wanted to show some idea of
what we can tackle next.
We can explore additional city elements,
roads, sidewalks, parks, and many more
things that I didn't include here.
We can improve the city layout. The city
here is the city layout is pretty basic
here.
We can create splinebased buildings,
ones that are not just square. Grammar
is already a huge help toward it and
geometry script can generate custom
sized roofs, floors, pipes, and more on
the fly.
PCGX is looking awesome. It's a plugin
that seems to address many of the needs
for complex city layout, having more
special nodes and things that can
measure if they are inside of each
other.
Interiors can be both challenging and
super interesting to tackle with PCG
and many more additional paths. Unreal
5.6 six features, interactive UI,
different styles, and combining it with
geo generation, pipes, and more.
Final thoughts.
PCG is not easy. It's sometimes simple,
but can easily get complex for certain
tasks.
A full complexity is a significant
challenge.
Geometry generation is currently basic
within PCG, but you can complement it
with geometry script.
Most spline vertex and face operations
could simplify the graphs and do certain
actions more easily like cubes to
splines.
PCG is super useful. Some buildings,
fences, biomes, and many tools are
totally viable now.
PCG can also be useful for level design
or gray boxing early in development
and it can also be used in the later
stages to scatter points on the
landscape or any mesh that we want
filter them and then spawn meshes
accordingly such as vegetation extra
rocks everything
is also stable it's fast and many
feature I kind of expected to have were
there a lot of nodes
It supports importing and editing point
clouds. So using an amic we can make it
much more useful basically deciding what
do we want to spawn. We can take the
point cloud and spawn additional points
around it.
And one more point that I wanted to say
is that anybody can sell those tools in
a huge marketplace which makes it a lot
more relevant now.
In the future, I hope Epics Epic keeps
developing PCG. Some things I would be
happy to see are animation or in general
just the ability to simulate and animate
anything using PCG. Maybe even author
blueprint or move characters using it.
One more thing is smaller graph. I want
less nodes. So let's say inline
constants are coming 5.6. six which will
make the graph significantly smaller. It
is nice.
Highle nodes such as selfining or just a
fence or building nodes will be great
because one of the workflows we can do
is to take those highle nodes, break
them down and change them a little bit
and get another tool al together
and advanced tutorials. It will help us
explore and learn what's possible.
We're done.
feel free to ask.
Thank you so much.
Thank you so so much. Feel free to ask
me questions either now or later. I will
be here and in the dev launch.
>> Um so what what would be your approach
to add more directability in the tools?
Like say the art director wants like I
don't want this building here or the
upper floor is too tall on this one or
the prop on that generated on the corner
like like being you generate everything
but still have access to like the
certain layers to prune and direct.
Right. So this is a really really cool
feature of PCG. Once we spawn those
building octals we can just click on one
of them and change all of the parameters
as if we just placed it manually. So we
can change the flows, we can change its
um its location or size without
regenerating the whole city. So this is
one approach we would go and using
splines and things like that to even
have more directability.
Um Paul if this was covered I came in
later but uh was there any actual engine
code changes involved or was this
completely it's one 100% PCG. Um Mudini
was used to just import the modules and
sort of pack them into an FBX. It was
easy because when I kind of change the
modules it automatically like picks
them, center them and export it as just
one file so I can reimpport in Unreal.
Got it. And also another question is um
was this uh is this being used with
world partition or like without because
we have tried using uh PCGS on our side
and the moment you get involved with
level instances and other things things
might go wrong at least it did for us.
>> I see yeah I didn't explore world
partition um I didn't check performance
a lot but I saw that it ran very very
quickly. So, let's say still capped at
120 fps for full HD. So, for now, I
didn't touch it, but yeah, it's
definitely something we should explore.
Thank you. Thank you.
Loading video analysis...