Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Procedural Content Generation with Unity
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
What is Procedural Content Generation?
Procedural Generation
with no or limited human intervention, algorithmically
of Content
of “things that affect the gameplay”, not non-player
character behavior, not the game engine
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
so what exactly is procedurally generated?
levels, tracks, maps, terrains, dungeons, puzzles,
buildings, trees, grass, fire, plots, descriptions,
scenarios, dialogues, quests, characters, rules,
boards, parameters, camera viewpoint, dynamics,
weapons, clothing, vehicles, personalities, etc.
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015http://en.wikipedia.org/wiki/Rogue_(video_game)#mediaviewer/File:Rogue_Screen_Shot_CAR.PNG
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
BBC Micro – 2 MHz MOS Technology 6502/6512
16-128 kB RAM 32-128 kB ROM
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015https://www.youtube.com/watch?v=ISR4ebdGlOk
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
what’s the basic principle?
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
f(x) = sin(x)
float y = 0f;
for (float x = 0f; x<6.28f; x+=.01f) {
y = Mathf.Sin(x);
}
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
What the ingredients?
domain knowledge
structured randomness
multi-layering
filters, limits & restrictions
specialized algorithms
artificial intelligence
gameplay integration
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Outline
geometry
textures
animations
dungeons
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Procedural Geometry
(Quads)
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
/// specify vertices
Vector3[] vertices = new Vector3[4];
vertices[0] = new Vector3(0.0f, 0.0f, 0.0f);
vertices[1] = new Vector3(0.0f, 0.0f, m_Length);
vertices[2] = new Vector3(m_Width, 0.0f, m_Length);
vertices[3] = new Vector3(m_Width, 0.0f, 0.0f);
/// specify 2 triangles
int[] indices = new int[6];
/// triangle 1
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
/// triangle 2
indices[3] = 0;
indices[4] = 2;
indices[5] = 3;
/// create the mesh
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = indices;
mesh.RecalculateBounds();
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
/// create the normals
Vector3[] normals = new Vector3[4];
normals[0] = Vector3.up;
normals[1] = Vector3.up;
normals[2] = Vector3.up;
normals[3] = Vector3.up;
mesh.normals = normals;
/// create the UV for the full texture
Vector2[] uv = new Vector2[4];
uv[0] = new Vector2(0.0f, 0.0f);
uv[1] = new Vector2(0.0f, 1.0f);
uv[2] = new Vector2(1.0f, 1.0f);
uv[3] = new Vector2(1.0f, 0.0f);
mesh.uv = uv;
/// create the UV for half texture
Vector2[] uv = new Vector2[4];
uv[0] = new Vector2(0.0f, 0.0f);
uv[1] = new Vector2(0.0f, 1.0f);
uv[2] = new Vector2(0.5f, 1.0f);
uv[3] = new Vector2(0.5f, 0.0f);
mesh.uv = uv;
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Procedural Geometry
(Polygons)
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
/// specify vertices
Vector3[] vertices = new Vector3[_no_sides];
float d = 2*Mathf.PI/no_sides;
for(int s=0; s<_no_sides; s++) {
vertices[s] = new Vector3(Mathf.Cos (-s*d), 0f,
Mathf.Sin (-s*d)) * _ray;
}
/// compute triangles no_sides-2 triangles, 3 indices each
int[] indices = new int[(_no_sides-2)*3];
for(int t=0; t<_no_sides-2; t++) {
indices[t*3] = t;
indices[t*3+1] = t+1;
indices[t*3+2] = vertices.Length-1;
}
/// ...
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Procedural Geometry
(Surfaces)
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
public class MeshBuilder
{
public List<Vector3> Vertices;
public List<Vector3> Normals;
public List<Vector2> UVs;
public void AddTriangle(int i0, int i1, int i2);
public Mesh CreateMesh()
}
MeshBuilder meshBuilder = new MeshBuilder();
//Set up the vertices and triangles:
meshBuilder.Vertices.Add(new Vector3(0.0f, 0.0f, 0.0f));
meshBuilder.UVs.Add(new Vector2(0.0f, 0.0f));
meshBuilder.Normals.Add(Vector3.up);
...
meshBuilder.AddTriangle(0, 1, 2);
meshBuilder.AddTriangle(0, 2, 3);
...
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
MeshBuilder meshBuilder = new MeshBuilder();
for (int i = 0; i < m_SegmentCount; i++)
{
float z = m_Length * i;
for (int j = 0; j < m_SegmentCount; j++)
{
float x = m_Width * j;
Vector3 offset =
new Vector3(x, Random.Range(0.0f, m_Height), z);
BuildQuad(meshBuilder, offset);
}
}
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Procedural Geometry
(Cubes, Cylinders, Flowers)
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Procedural Generation of Textures
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
structured noise
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
// Create the new texture
texture = new Texture2D(width, height, TextureFormat.RGBA32,
false);
// Assign it to the material
GetComponent<MeshRenderer>().material.mainTexture = texture;
// Generate the pixels
for (int y = 0; y < height; y++){
for (int x = 0; x < width; x++){
R = …
G = …
B = …
A = …
texture.SetPixel(x, y,
new Color (R, G, B, A));
}
}
// Apply the texture
texture.Apply();
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
// Noise pattern
noiseR =
SimplexNoise.noiseOctaves(nOctaves,xx*betaWR,yy,seed,frequenc
y);
// Alpha blending
valueR = (1-alphaR)+alphaR*noiseR;
// Sine pattern
valueR *= Mathf.Sin(noiseR*(sineX*x+sineY*y)*sineFrequency);
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Procedural Animations
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Procedural Animation
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Animation in Unity
Skinned mesh renderer
Transforms = Bones
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
// Get all children transforms
var bones = gameObject.GetComponentsInChildren<Transform>();
// Rotate them using a sine wave
foreach(var bone in bones)
{
// Create a sine wave
float angle = Mathf.Sin(t + phase)*amplitude;
// Assign rotation
Vector3 tmpRot = bone.localEulerAngles;
tmpRot.z = angle;
bone.localEulerAngles = tmpRot;
}
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Dungeon Generation
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Dungeon Generation
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
The Grid Map
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
// Mark the starting location
CellLocation currentLocation = starting_location;
map.MarkAsVisited(currentLocation);
// Pick a starting direction
Direction previousDirection = Direction.North;
// Repeat until all cells have been visited
while (!map.AllCellsVisited)
{
// Choose a direction
DirectionPicker directionPicker =
new DirectionPicker(map, currentLocation, directionChangeModifier,
previousDirection);
Direction direction = directionPicker.GetNextDirection(map, currentLocation);
// Check if we can go in that direction
if (direction != Direction.None)
{
// Create a corridor to the next cell and flag this cell as visited
previousLocations.Add(currentLocation);
previousDirection = direction;
currentLocation = map.CreateCorridor(currentLocation, direction);
map.FlagCellAsVisited(currentLocation);
} else {
// Backtrack
currentLocation = previousLocations[previousLocations.Count - 1];
previousLocations.RemoveAt(previousLocations.Count - 1);
}
Recursive Backtracking algorithm
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Virtual Map -> Physical Map
// Choose a prefab based on the cell type
GameObject prefab = behaviour.GetPrefab(cell_type);
// Instantiate the prefab at the given position
GameObject go = (GameObject)GameObject.Instantiate(prefab, new
Vector3(l.x*behaviour.tileSize,l.storey*(behaviour.wallHeight
+behaviour.storeySeparationHeight),l.y*behaviour.tileSize),
Quaternion.identity);
go.name = cell_type.ToString();
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
we can do it, so can you!
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
http://www.youtube.com/watch?v=uIUYWzdMXog
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015http://www.michelepirovano.com/portfolio_swordgenerator.php
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015http://www.michelepirovano.com/portfolio_swordgenerator.php
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
http://www.polimigamecollective.org
http://www.facebook.com/polimigamecollective
http://www.youtube.com/PierLucaLanzi
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
47
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Ingredients #1 & #2
Domain Knowledge & Artificial Intelligence
•  Domain Knowledge
§ To generate something you need to know it
§ PCG typically aims at building an artificial level
designer, usually needs domain knowledge
about level design
•  Artificial Intelligence
§ Need algorithms that can work on complex
knowledge and generate plausible content
§ Search-based methods, L-systems, evolutionary
computation, fractals, cellular automata,
agent-based methods, planning, etc.
48
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
ingredient #3
structured randomness
things look like they have been randomly
generated but it is not completely at random!
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
f(x) = sin(x)
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
they both look like “noise”
but one of them feels like it has structure…
it is structured randomness
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
ingredient #4
multi-layering
typically more layers of procedural
content generation are applied in sequence
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
•  Warzone 2100
§ Heights & Cliffs
§ Roads
§ Textures
§ Player Bases
§ Local Features
•  Civilization 4
§ Fractal Heightfield
§ Plate Tectonics
§ Tile Types
§ Rivers and Lakes
§ Map Bonuses
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
ingredient #5
Filters, Limits & Restrictions
“In Civ3 I would say we even shipped with a sub-standard resource
placement algorithm where all the iron could be concentrated in just
a few small locations on the map, and for one player there may be
literally no way for them to build swordsmen.” – Soren Johnson
"With Civ4 we instituted randomness with limitations. There
always has to be a minimum distance between each element of
iron, or each element of horses, and that completely solved the
problem.” – Soren Johnson
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
ingredient #6
specialized algorithms
placing special items, requires special tricks
this tricks must be encoded in the PCG
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
1.  Connect all bases, the resources,
pick three random points and
connect them
2.  Apply a customize A* heuristic
and reuse roads!
3.  Customize A* heuristic with
randomize cost of non-road
grid cells.
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015
ingredient #7
gameplay integration
Is it fun to play? Is the progression adequate?
Pier Luca Lanzi e Michele Pirovano – Codemotion Milan November 2015

Codemotion Milan - November 21 2015

  • 1.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Procedural Content Generation with Unity
  • 2.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 What is Procedural Content Generation? Procedural Generation with no or limited human intervention, algorithmically of Content of “things that affect the gameplay”, not non-player character behavior, not the game engine
  • 3.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 so what exactly is procedurally generated? levels, tracks, maps, terrains, dungeons, puzzles, buildings, trees, grass, fire, plots, descriptions, scenarios, dialogues, quests, characters, rules, boards, parameters, camera viewpoint, dynamics, weapons, clothing, vehicles, personalities, etc.
  • 4.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015http://en.wikipedia.org/wiki/Rogue_(video_game)#mediaviewer/File:Rogue_Screen_Shot_CAR.PNG
  • 5.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015
  • 6.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 BBC Micro – 2 MHz MOS Technology 6502/6512 16-128 kB RAM 32-128 kB ROM
  • 7.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015https://www.youtube.com/watch?v=ISR4ebdGlOk
  • 8.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015
  • 9.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015
  • 10.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 what’s the basic principle?
  • 11.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 f(x) = sin(x) float y = 0f; for (float x = 0f; x<6.28f; x+=.01f) { y = Mathf.Sin(x); }
  • 12.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 What the ingredients? domain knowledge structured randomness multi-layering filters, limits & restrictions specialized algorithms artificial intelligence gameplay integration
  • 13.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Outline geometry textures animations dungeons
  • 14.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Procedural Geometry (Quads)
  • 15.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015
  • 16.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 /// specify vertices Vector3[] vertices = new Vector3[4]; vertices[0] = new Vector3(0.0f, 0.0f, 0.0f); vertices[1] = new Vector3(0.0f, 0.0f, m_Length); vertices[2] = new Vector3(m_Width, 0.0f, m_Length); vertices[3] = new Vector3(m_Width, 0.0f, 0.0f); /// specify 2 triangles int[] indices = new int[6]; /// triangle 1 indices[0] = 0; indices[1] = 1; indices[2] = 2; /// triangle 2 indices[3] = 0; indices[4] = 2; indices[5] = 3; /// create the mesh Mesh mesh = new Mesh(); mesh.vertices = vertices; mesh.triangles = indices; mesh.RecalculateBounds();
  • 17.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 /// create the normals Vector3[] normals = new Vector3[4]; normals[0] = Vector3.up; normals[1] = Vector3.up; normals[2] = Vector3.up; normals[3] = Vector3.up; mesh.normals = normals; /// create the UV for the full texture Vector2[] uv = new Vector2[4]; uv[0] = new Vector2(0.0f, 0.0f); uv[1] = new Vector2(0.0f, 1.0f); uv[2] = new Vector2(1.0f, 1.0f); uv[3] = new Vector2(1.0f, 0.0f); mesh.uv = uv; /// create the UV for half texture Vector2[] uv = new Vector2[4]; uv[0] = new Vector2(0.0f, 0.0f); uv[1] = new Vector2(0.0f, 1.0f); uv[2] = new Vector2(0.5f, 1.0f); uv[3] = new Vector2(0.5f, 0.0f); mesh.uv = uv;
  • 18.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Procedural Geometry (Polygons)
  • 19.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 /// specify vertices Vector3[] vertices = new Vector3[_no_sides]; float d = 2*Mathf.PI/no_sides; for(int s=0; s<_no_sides; s++) { vertices[s] = new Vector3(Mathf.Cos (-s*d), 0f, Mathf.Sin (-s*d)) * _ray; } /// compute triangles no_sides-2 triangles, 3 indices each int[] indices = new int[(_no_sides-2)*3]; for(int t=0; t<_no_sides-2; t++) { indices[t*3] = t; indices[t*3+1] = t+1; indices[t*3+2] = vertices.Length-1; } /// ...
  • 20.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Procedural Geometry (Surfaces)
  • 21.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 public class MeshBuilder { public List<Vector3> Vertices; public List<Vector3> Normals; public List<Vector2> UVs; public void AddTriangle(int i0, int i1, int i2); public Mesh CreateMesh() } MeshBuilder meshBuilder = new MeshBuilder(); //Set up the vertices and triangles: meshBuilder.Vertices.Add(new Vector3(0.0f, 0.0f, 0.0f)); meshBuilder.UVs.Add(new Vector2(0.0f, 0.0f)); meshBuilder.Normals.Add(Vector3.up); ... meshBuilder.AddTriangle(0, 1, 2); meshBuilder.AddTriangle(0, 2, 3); ...
  • 22.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 MeshBuilder meshBuilder = new MeshBuilder(); for (int i = 0; i < m_SegmentCount; i++) { float z = m_Length * i; for (int j = 0; j < m_SegmentCount; j++) { float x = m_Width * j; Vector3 offset = new Vector3(x, Random.Range(0.0f, m_Height), z); BuildQuad(meshBuilder, offset); } }
  • 23.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015
  • 24.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Procedural Geometry (Cubes, Cylinders, Flowers)
  • 25.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015
  • 26.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015
  • 27.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015
  • 28.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Procedural Generation of Textures
  • 29.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 structured noise
  • 30.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015
  • 31.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 // Create the new texture texture = new Texture2D(width, height, TextureFormat.RGBA32, false); // Assign it to the material GetComponent<MeshRenderer>().material.mainTexture = texture; // Generate the pixels for (int y = 0; y < height; y++){ for (int x = 0; x < width; x++){ R = … G = … B = … A = … texture.SetPixel(x, y, new Color (R, G, B, A)); } } // Apply the texture texture.Apply();
  • 32.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 // Noise pattern noiseR = SimplexNoise.noiseOctaves(nOctaves,xx*betaWR,yy,seed,frequenc y); // Alpha blending valueR = (1-alphaR)+alphaR*noiseR; // Sine pattern valueR *= Mathf.Sin(noiseR*(sineX*x+sineY*y)*sineFrequency);
  • 33.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Procedural Animations
  • 34.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Procedural Animation
  • 35.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Animation in Unity Skinned mesh renderer Transforms = Bones
  • 36.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 // Get all children transforms var bones = gameObject.GetComponentsInChildren<Transform>(); // Rotate them using a sine wave foreach(var bone in bones) { // Create a sine wave float angle = Mathf.Sin(t + phase)*amplitude; // Assign rotation Vector3 tmpRot = bone.localEulerAngles; tmpRot.z = angle; bone.localEulerAngles = tmpRot; }
  • 37.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Dungeon Generation
  • 38.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Dungeon Generation
  • 39.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 The Grid Map
  • 40.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 // Mark the starting location CellLocation currentLocation = starting_location; map.MarkAsVisited(currentLocation); // Pick a starting direction Direction previousDirection = Direction.North; // Repeat until all cells have been visited while (!map.AllCellsVisited) { // Choose a direction DirectionPicker directionPicker = new DirectionPicker(map, currentLocation, directionChangeModifier, previousDirection); Direction direction = directionPicker.GetNextDirection(map, currentLocation); // Check if we can go in that direction if (direction != Direction.None) { // Create a corridor to the next cell and flag this cell as visited previousLocations.Add(currentLocation); previousDirection = direction; currentLocation = map.CreateCorridor(currentLocation, direction); map.FlagCellAsVisited(currentLocation); } else { // Backtrack currentLocation = previousLocations[previousLocations.Count - 1]; previousLocations.RemoveAt(previousLocations.Count - 1); } Recursive Backtracking algorithm
  • 41.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Virtual Map -> Physical Map // Choose a prefab based on the cell type GameObject prefab = behaviour.GetPrefab(cell_type); // Instantiate the prefab at the given position GameObject go = (GameObject)GameObject.Instantiate(prefab, new Vector3(l.x*behaviour.tileSize,l.storey*(behaviour.wallHeight +behaviour.storeySeparationHeight),l.y*behaviour.tileSize), Quaternion.identity); go.name = cell_type.ToString();
  • 42.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 we can do it, so can you!
  • 43.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 http://www.youtube.com/watch?v=uIUYWzdMXog
  • 44.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015http://www.michelepirovano.com/portfolio_swordgenerator.php
  • 45.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015http://www.michelepirovano.com/portfolio_swordgenerator.php
  • 46.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 http://www.polimigamecollective.org http://www.facebook.com/polimigamecollective http://www.youtube.com/PierLucaLanzi
  • 47.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 47
  • 48.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 Ingredients #1 & #2 Domain Knowledge & Artificial Intelligence •  Domain Knowledge § To generate something you need to know it § PCG typically aims at building an artificial level designer, usually needs domain knowledge about level design •  Artificial Intelligence § Need algorithms that can work on complex knowledge and generate plausible content § Search-based methods, L-systems, evolutionary computation, fractals, cellular automata, agent-based methods, planning, etc. 48
  • 49.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015
  • 50.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 ingredient #3 structured randomness things look like they have been randomly generated but it is not completely at random!
  • 51.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 f(x) = sin(x)
  • 52.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015
  • 53.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 they both look like “noise” but one of them feels like it has structure… it is structured randomness
  • 54.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015
  • 55.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 ingredient #4 multi-layering typically more layers of procedural content generation are applied in sequence
  • 56.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 •  Warzone 2100 § Heights & Cliffs § Roads § Textures § Player Bases § Local Features •  Civilization 4 § Fractal Heightfield § Plate Tectonics § Tile Types § Rivers and Lakes § Map Bonuses
  • 57.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 ingredient #5 Filters, Limits & Restrictions “In Civ3 I would say we even shipped with a sub-standard resource placement algorithm where all the iron could be concentrated in just a few small locations on the map, and for one player there may be literally no way for them to build swordsmen.” – Soren Johnson "With Civ4 we instituted randomness with limitations. There always has to be a minimum distance between each element of iron, or each element of horses, and that completely solved the problem.” – Soren Johnson
  • 58.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 ingredient #6 specialized algorithms placing special items, requires special tricks this tricks must be encoded in the PCG
  • 59.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 1.  Connect all bases, the resources, pick three random points and connect them 2.  Apply a customize A* heuristic and reuse roads! 3.  Customize A* heuristic with randomize cost of non-road grid cells.
  • 60.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015 ingredient #7 gameplay integration Is it fun to play? Is the progression adequate?
  • 61.
    Pier Luca Lanzie Michele Pirovano – Codemotion Milan November 2015