Tiny Simulations Package
You can download this unity package here, it contains some demos of commonly used techniques for building simulations.
Randomization, Simulation, Generators
Why? Computers are great at receiving some input and returning a result. The deterministic qualities of a computer are what make it useful.
You want to know that when you create a text file or save a png that the text or the pixels won’t change every time you open the file.
Compare this with how our own brains recall memories, each recall is slightly distorted and affected by time, environment and mood.
Apps can play with our expectations of permanence (most dangerous writing app) and it isn’t uncommon to encounter an image or video that is a rip of a photo or a screenshot of a backup of a video recorded from a tv screen (In defense of the poor image).
So it takes a bit of human intervention to introduce randomness to deterministic machines. Maybe this is why randomness is so alluring, it adds a touch of humanity.
Process
- What do you want to generate?
- What are the properties and constraints of your thing?
- What are the methods for generating these things?
- Generate things
- Evaluate, modify, repeat
(alt approach – start with method first or reverse engineer some objects)
Consider perceptual differentiation vs perceptual uniqueness. Is it enough to tell that each new output is different from the previous one, or should the output also be totally unique? All discussed in So you want to build a generator
Generating things
A hundred thousand billion poems - Raymond Queneau (coded)
You don’t need to build every single house in a city as long as you have a set of blocks and components that would ultimately comprise enough variety to give the impression of a complex city.
A big part of generation involves understanding a particular typology, recognizing the core components of what might define a character/story/object/sound and defining the variations that you can explore within that theme
Hans Eijkelboom – People of the Twenty-first Century
Creating images, simulations and movements
Mirror Lake - Everest Pipkin
Lichenia - Molleindustria
Emergent behavior
Braitenberg Vehicle - more info here
Steering algorithms / boids / agent behaviors (nature of code)
Emergent behavior refers to the phenomenon where complex systems exhibit properties, patterns, or behaviors that arise from the interactions of simpler components within the system.
These emergent properties are not explicitly programmed or designed but arise spontaneously as a result of the interactions and relationships between the system’s components.
See also Autopoiesis – the self-maintaining and self-reproducing nature of living systems. Autopoietic systems give rise to emergent properties. (book)
Reaction diffusion – simulation of two virtual chemicals
https://ncase.me/sim/ – Cellular Automata
Emissary Forks For You (2016) – Ian Cheng
Boid simulation, steering, autonomous agents, and “Sim” games. Stories and narratives can come into being even when based on simple sets of rules.
See patch notes for unexpected outcomes of the dwarf fortress systems:
Modular Architecture
Create a program that designs buildings out of modular parts, with a variety of terraces, flags, windows, roofing, materials, telephone wires, banners, and more.
Are you emulating an existing architectural style? Or are you designing Escher-like impossible architectures?
Vietnam Romance - Eddo Stern Features cityscapes made out of randomly generated modular buildings. Each building is constructed from a variety of roofs, floors, window decorations, awnings, and signs.
See also: Wave Function Collapse
https://selfsame.itch.io/unitywfc or https://marian42.de/article/wfc/ – based on : https://github.com/mxgmn/WaveFunctionCollapse
While the final result may seem effortless. There is quite a bit of preparatory work in designing modular sections as well as defining the rules for how each section fits together.
Most often used in generating landscape / maps. However this is not the only algorithm
https://www.badnorth.com/ – see Oskar Stalberg give a talk on WFC usage in Bad North
Generative Landscape
Write a program that presents an ever-changing, imaginative landscape. Populate your landscape with features that are suitable for your concept: trees, buildings, vehicles, animals, people, food, body parts, hairs, seaweed, space junk, zombies, etc.
While there are many techniques for generating “realistic” landscapes (see Sebastian Lague’s series of videos), your landscape does not need to follow those conventions. Consider Mirror Lake above. While the scale isn’t completely clear, there is a consistent substrate (the lake / bowl / pot), and the random variation happens in the growth and surrounding areas.
Really consider the scale that you are trying to generate. Is it a planet, a garden, or a leaf? How does the viewer navigate or experience your landscape? Are things constantly being generated or does the interaction take place post-generation? Does the camera fly through it? Does the camera orbit?
Proteus - David Kanaga Players explore a large, generative island in 3D. The island is populated by low-res trees, flowers, and more. The soundscape changes based on the weather, time of day, and other factors.
Genetic Algorithm
Write a program that presents the user with several randomly generated options. The user picks a few, and a new set is produced based on the user’s selections.
A genetic algorithm needs three things:
- A thing you can modify (a ‘genotype’)
- A thing you can judge (a ‘phenotype’)
- A way to turn the first into the second
Kate Compton - Flower Generator
Automata
Write a program that creates a dynamic visual system using cellular automata or other dynamic agents that change state based on their neighbors.
See the Emoji Simulator by Nicky Case for a great interactive example of cellular automata in action.
This blog post does a decent job explaining cellular automata: https://tatasz.github.io/compound_ca/
Tiny Simulations Package
You can download this unity package here, it contains some demos of common
Scene 1: Generating objects
After downloading the unitypackage. Open the package in a new or existing URP project and open the “generate-objects” scene under Scenes > generate-objects.
This scene is pretty simple: a platform and a few spawners that we can use to test out different methods for instantiating objects.
Let’s start with the basic spawning script:
using System.Collections;
using UnityEngine;
public class SpawnGameObject : MonoBehaviour
{
// prefab to spawn
public GameObject prefab;
[Range(0.1f,8f)]
public float ratePerSecond = 1f;
void Start()
{
// use a coroutine to control the spawn rate
StartCoroutine(Spawn());
}
IEnumerator Spawn(){
// infinite loop
while(true){
// spawn the prefab
Instantiate(prefab, transform.position, transform.rotation);
// wait a moment before next loop
yield return new WaitForSeconds(1f/ratePerSecond);
}
}
}
This combines Instantiate with a Coroutine to continuously spawn a new prefab at a specific interval.
Attach the script to an empty game object. Create a prefab and drag it into the script’s prefab slot in the inspector. Press play and see if the prefab spawns.
What are ways to complicate things?
Spawn prefabs over a range of positions…
- Using Random.InsideUnitSphere or Random.OnUnitSphere or Random.Range
Spawn multiple prefabs each time…
- For loop wrapped around Instantiate
Animate the spawner to create a pattern of prefabs…
- Using the Animation system
- Animating the position and rotation with script … in Update loop
- … or give the spawner a RigidBody and add forces to it
Adding a force to the spawned prefabs (could also be done on the prefab itself)
- GetComponent -> AddForce (don’t forget
ForceMode.Impulse
)
Adding collision detection to the prefabs
- Spawn more objects/images/sounds/particles on collision
- Change colors on collision
Randomly spawning from an array of prefabs…
// array to fill with prefabs in the inspector
public GameObject[] prefabs;
//...
// inside the coroutine
// pick random prefab from the array
GameObject randomPrefab = prefabs[Random.Range(0, prefabs.Length)];
// spawn it
Instantiate(randomPrefab, transform.position, transform.rotation);
Add to the array of prefabs in the inspector:
Face Shuffler
We could use this technique to spawn prefabs at specific locations. Here’s an example script that uses preset GameObjects, but randomly switches the textures on the objects:
using UnityEngine;
public class FaceShuffler : MonoBehaviour
{
public GameObject eyes;
public GameObject nose;
public GameObject mouth;
public Texture[] eyeTextures;
public Texture[] noseTextures;
public Texture[] mouthTextures;
void Start()
{
Shuffle();
}
public void Shuffle()
{
// pick random textures
var randEye = GetRandomTexture(eyeTextures);
var randNose = GetRandomTexture(noseTextures);
var randMouth = GetRandomTexture(mouthTextures);
// update the texture on each object
SetTexture(eyes, randEye);
SetTexture(nose, randNose);
SetTexture(mouth, randMouth);
}
public void SetTexture(GameObject obj, Texture tex)
{
obj.GetComponent<Renderer>().material.SetTexture("_BaseMap", tex);
}
public Texture GetRandomTexture(Texture[] textures)
{
return textures[Random.Range(0, textures.Length)];
}
}
You can download this unitypackage with the scene to test it out.
Spawning prefabs from spawned prefabs: Chain Link
You can spawn prefabs that also contain an object spawner. It’s important to be careful to avoid runaway spawners that could cause crashing or freezing. In this example, there is a maximum number of layers that are allowed to spawn and the spawner will only spawn when the linkPrefab variable is not null. It’s possible to prevent further generation by setting the linkPrefab value to null in the newly instantiated game object.
using UnityEngine;
public class SpawnLink : MonoBehaviour
{
public GameObject linkPrefab;
public float length = 5f;
public float angleVariation = 10f;
public float delay = 1f;
public int branchesPerSpawn = 2;
public int maxLinks = 5;
static int linkCount = 0;
void Start()
{
// add more to the link count
linkCount++;
// spawn after delay
Invoke("Spawn", delay);
}
void Spawn()
{
if(linkPrefab != null)
{
for(int i = 0; i < branchesPerSpawn; i++)
{
// move to end of this prefab
Vector3 spawnPos = transform.position + transform.up * length;
// adjust the direction
Vector3 spawnRot = transform.rotation.eulerAngles + new Vector3(
Random.Range(-angleVariation, angleVariation),
Random.Range(-angleVariation, angleVariation),
Random.Range(-angleVariation, angleVariation));
// spawn the link
GameObject link = Instantiate(linkPrefab, spawnPos, Quaternion.Euler(spawnRot));
if (linkCount > maxLinks)
{
link.GetComponent<SpawnLink>().linkPrefab = null;
}
}
}
}
}