Introducing Variation

This tutorial introduces the use of randomisation to vary generation and how seeds and their propagation can be used to control this randomness.


  • This tutorial modifies the procedure created in the Basic Iteration tutorial, so please make sure you are using a project where you've already followed it.

Primary Goals

  • Basic randomisation
  • Basic seed use
  • Seed propagation

Secondary Goals

  • High level parameterisation
  • Passing values down through a procedure hierarchy


Create Variation Procedure

First we will create a new procedure to encapsulate the variation we want to apply to the blocks in the stack.

  1. Create a new procedure called "Vary Placement"
  2. Add an operator to rotate a frame relative to itself (Turn)
  3. Add a random floating point number operator (RandomF)
  4. Add a floating point 'spread' operator (SpreadF) to generate a range around 0
  5. Set up the rotation operator:
    1. Drag its frame in/out off the left/right to form the main procedure input/output
    2. Feed the rotation Amount from the random Value
    3. Set the Axis of rotation to Z
  6. Set up the random number generator:
    1. Drag its seed in/out (presented as a # symbol by convention) off the left/right to form procedure seed in and out
    2. Rename the # input to "Seed"
    3. Feed the random range min/max from the outputs of the spread operator
  7. Set up the spread operator:
    1. Ensure the In value is 0 (centre of range)
    2. Drag the +/- input off the left and call it "Turn"
  8. Configure the Turn input metadata to have a range of 0 to 180 (turn operator uses degrees)
  9. Save

Your variation procedure should look something like this:

Modify Block Stacking Procedure

We can now modify the Test.Block Stack procedure to use this new variation procedure.

  1. Open the Test.Block Stack procedure
  2. Drag in an instance of the new Test.Vary Placement procedure
  3. Reconnect the Shiny Cube Where? input so that the Vary Placement operator interrupts the incoming frame (from the Cube input)
  4. Add a new input to feed the seed (#) input of Vary Placement procedure.
  5. Feed the seed output (#) of the Vary Placement procedure into the recursive instance of the Block Stack procedure.
  6. Add a new input to feed the Turn input of the Vary Placement procedure. Note that you will also need to pass this on to the recursive Block Stack procedure so that each new block along the chain knows what the turn range should be.

Your modified block stacking procedure should look like this:


Notice that as you add inputs to the main procedure outline, they also appear on the instance of it you have placed down inside.
Passing the output seed into the next iteration of the procedure creates a chain of seeds through the stack, each one different and based on the last. These ensure that each placed block will have a different variation applied.
Optionally, you can also change the Offset operator input from the Cube input to the varied version of the frame from the previous block. Both will work but produce slightly different behvaiour (play with the inputs of a placed entity and see if you can work out what). This might be more noticable if you apply a random positional offset instead of just turning each block.
Play with where the next seed comes from, if you don't want to use the new value out of the varying procedure (or can't in some cases), you can connect it to the incoming seed instead. Try it to see the result. You can overcome this problem by using the RandomTwist operator to derive a new seed stream from an existing one and feed each new instance with that instead.


Your placed instances of the block stack will now have two new inputs, the seed value and the turn amount. Play with these, and the original parameters to see how your new procedure behaves.

Next Steps

To learn more about these techniques check out the A Case Of Non-Randomness - Part 1 blog post about randomness, sequences, determinism, seeds, propagation, and how they are handled in Apparance.