Procedural Generation - aefreedman/SP2018_IntermediateGameDev GitHub Wiki

You will be making something kind of like what Vlambeer did for "Nuclear Throne". Read this (broken)

gif

EXAMPLE FROM PAST SEMESTER

STEP 1) Make a simple tile prefab placeholder in Unity

Make a simple flat cube (scale: 5, 1, 5) and convert it into a prefab (drag-and-drop from Hierarchy into Project tab).

Remember: Prefabs are GameObjects that live outside of scenes. More info on Prefabs. Short video tutorial.

STEP 2) Make a new script called Pathmaker.cs

More info on instantiation

// put this on a small sphere, it will drop a "breadcrumb" trail of floor tiles
PathMaker.cs:

DECLARE CLASS MEMBER VARIABLES:
Declare a private integer called counter that starts at 0;
Declare a public Transform called floorPrefab, assign the prefab in inspector;
Declare a public Transform called pathmakerSpherePrefab, assign the prefab in inspector;
// you'll have to make a "pathmakerSphere" prefab later

// in one example on Monday, we generated the entire world instantly in Start()... in this case, we will generate it during Update instead, so we see the world unfold in front of us
UPDATE:
If counter is less than 50, then:
    Generate a random number from 0.0f to 1.0f;
    If random number is less than 0.25f, then rotate myself 90 degrees;
    ... Else if number is 0.25f-0.5f, then rotate myself -90 degrees;
    ... Else if number is 0.99f-1.0f, then instantiate a pathmakerSpherePrefab clone at my current position;
    // end elseIf
    Instantiate a floorPrefab clone at current position;
    Move forward ("forward" in local space, relative to the direction I'm facing) by 5 units;
    Increment counter;
Else:
    Destroy self;

STEP 3) implement it, test it, stabilize it

Implement and test

  • Save your scene!!! the code could potentially be infinite / exponential and make Unity crash
  • Put pathmaker.cs on a sphere
  • Configure all the prefabs in the Inspector
  • Test it

Stabilize

Code your generator so that all the Pathmakers can only spawn a grand total of 500 tiles in the entire world.

Hint: You could declare a public static int and have each Pathmaker check this global variable.

STEP 4) Tune it

  • How long should a pathmaker live? etc.
  • How would you tune the probabilities to generate lots of long hallways?
  • Tweak all the probabilities that you want
    • What is the probability that a pathmaker instantiates a pathmaker?
  • Review our idea of probability "buckets"
    • e.g. we had 50% chance to spawn a slow NPC, and 50% chance to make a fast NPC, instead of 95% chance of making a medium NPC?
    • In games, we often want to avoid homogeneous "muddy middle" averages

STEP 5) randomize it even more

  • Randomize two more variables in Pathmaker.cs for each different Pathmaker
    • Do this in Start()
  • Maybe randomize each pathmaker's lifetime?
  • Maybe randomize the probability it will turn right?
  • If there's a number in your code, you can randomize it

STEP 6) art pass, usability pass

  • move the game camera to a position high in the world, and then point it down, so we can see your world get generated
  • CHANGE THE DEFAULT UNITY COLORS, PLEASE, I'M BEGGING YOU
  • Add more detail to your original floorTile placeholder
    • Let it randomly pick one of three different floorTile model
      • For example, it could randomly pick a "normal" floor tile, a cactus, a rock, or a skull
  • MODEL 3 DIFFERENT TILES IN MAYA! DON'T STOP USING MAYA OR YOU'LL FORGET IT ALL
  • Add a simple in-game restart button
    • Let us press R to reload the scene and see a new level generate
  • Make a Canvas
    • Display the name of your generator on the Canvas
    • Tell us that we can press R to reset the generator

Bonus optional tasks if you want to do more

  • (intermediate) position the camera to center itself based on your generated world
    • One way: track the highest and lowest X and Y values of all of your tiles and point your camera at the midpoint
  • (intermediate) learn how to use UI Sliders (Tutorial) and let us tweak various parameters and settings of our tech demo, then let us click a UI Button to reload the scene, so we don't need the keyboard anymore
  • (advanced, time-consuming) add a second "wall" pass to your proc gen after it generates all the floors
    • raycast downwards around each floor tile (that'd be 8 raycasts per floor tile, in a square "ring" around each tile?)
    • if the raycast "fails" that means there's empty void there, so then instantiate a Wall tile prefab
    • repeat until walls surround your entire floorplan
      • (you'll get a lot of pointless repeat raycasts, but the "proper" way to do this would involve keeping a bitmap or 2D array of your entire map space, etc.)
      • (another way to add walls: (1) while instantiating floors, also instantiate walls around every floor tile, unless there's already a floor tile detected via raycast... (2) when FloorMaker moves, it "tunnels" through walls and deletes any wall it moves into)