Project 3 Sketches and Experiments
Checking in on how projects are going. Looking to see some progress on experiments with ideas.
Additional guides
If you find yourself a bit stuck. These are some other guides / walkthroughs / resources:
Noise and randomness
The basics of getting random values in Unity (Manual, API):
// getting numbers
float x = Random.value // value between 0 and 1 (inclusive)
float y = Random.Range(-100f, 100f);
int randomIndex = Random.Range(0, MyArray.Length); // get random index from array
// getting points / positions / vectors
float radius = 10f;
Vector3 randomPosition = Random.insideUnitSphere * radius; // within sphere
Vector2 random2DPosition = Random.insideUnitCircle * radius; // within circle
// Random color
Color randomColor = Random.ColorHSV(minHue, maxHue); // see API doc for full reference
// Random Rotation
transform.rotation = Random.rotation;
You can also use Random.value
to create probabilities for events to occur:
float probability = 0.8f; // 80% chance
if(Random.value < probability)
{
// do something
}
Smooth randomness with noise
Calling successive random values from Random.value
results in successive, but disconnected values. When you’d like to sample random values that can smoothly move from one value to another, you can use the Perlin Noise algorithm.
Perlin noise can be useful for adding more organic movement to objects, variation in textures, and heights in a landscape.
Check this update to the Unitypackage for demos involving Perlin Noise
Import the Unitypackage into your project (URP) and open the scene called “Noise”
Generating a noise texture
In the scene, the active object called “PerlinNoiseTexture” contains a script that will generate a texture and apply it to a cube. Generating a texture is also something new that you could use elsewhere if you need to create custom textures while your game is running.
In Unity the Mathf class contains Perlin Noise which can be used to sample 2D noise values at different x and y coordinates.
float value = Mathf.PerlinNoise(xCoord, yCoord);
Each coordinate will return a value between 0.0 and 1.0. The distance between successive coordinates can control the variation of the sampled values. Smoother changes will have shorter distances between two points.
Creating the texture involves defining a new Texture2D with a width and a height. This creates a canvas where you can specify the color of each pixel.
Texture2D texture = new Texture2D(width, height);
Set the pixel color by giving the coordinates of that pixel and a Color (all values are between 0 and 1):
Color color = new Color(1, 0.92, 0.016); // set RGB of the color
texture.SetPixel(x, y, color);
When generating a perlin noise texture, we’ll use the pixel X and Y coordinates of the texture as coordinates for the Perlin Noise method.
The script encapsulates all of this into a method:
Color CalclulateColor(int x, int y)
{
// convert from pixel coords to perlin coords
float xCoord = (float)x / width * scale;
float yCoord = (float)y / height * scale;
float value = Mathf.PerlinNoise(xCoord, yCoord);
return new Color(value, value, value);
}
While you could directly use the pixel coordinates, the conversion lets us vary how “zoomed” we are in the noise space.
The script loops through every pixel of the texture and sets the color using this CalculateColor method:
Texture2D GenerateTexture()
{
Texture2D texture = new Texture2D(width, height);
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
Color color = CalclulateColor(x, y);
texture.SetPixel(x, y, color);
}
}
// have to call this or the texture won't update
texture.Apply();
return texture;
}
Take a look at the script in the unity package to see it in its entirety. There is a separate method that demonstrates using multiple layers of noise, also known as multi-octave or fractal noise which are often used to generate more “natural” looking noise. See Catlike-coding for a bunch of in-depth tutorials on pseudorandom noise
Movement with randomness and noise
Comment out the PerlinNoiseTexture game object and uncomment the RandomWalk object.
This object has a script that demonstrates three different types of random movement.
Using Random.onUnitSphere to pick random directions for a cube to move
void MoveRandom()
{
// pick a random direction
Vector3 randomDirection = Random.onUnitSphere;
// move a bit in that direction
transform.position += randomDirection * Time.deltaTime;
}
Using a random value with different thresholds to determine the direction of movement
void MoveWeightedRandom()
{
// pick random value
float value = Random.value;
Vector3 movement = Vector3.zero;
// use these values to control the weights of the agent's movement
if (value < 0.4)
{
movement = Vector3.left;
}
else if (value < 0.6)
{
movement = Vector3.right;
}
else if (value < 0.8)
{
movement = Vector3.forward;
}
else
{
movement = Vector3.forward;
}
// move that direction
transform.position += movement * Time.deltaTime;
}
Using perlin noise to control movement
void MoveWithPerlinNoise()
{
// move through perlin space over time
float newX = Mathf.PerlinNoise(Time.time, 0) * 10f;
float newZ = Mathf.PerlinNoise(0, Time.time) * 10f;
Vector3 movement = new Vector3(newX, 0, newZ);
// move that direction
//transform.position += movement * Time.deltaTime;
transform.position = movement;
}
By using Time.time
, it’s possible to walk through the noise space.
Spawning with noise
Just as we used the coordinate values of noise to pick a color for a texture, the value can also be used to set the height of many objects.
The next game object, RandomSpawning, has a script that generates a grid of prefabs. The grid coordinates are also used to sample from perlin noise, and that value determines the height at which the prefab will be spawned.
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
// calculate the height
float height = heightScale * Mathf.PerlinNoise(i * noiseScale, j * noiseScale);
Instantiate(prefab, new Vector3(i, height, j), Quaternion.identity);
}
}
The script in the scene also stores each instantiated object in an array. This allows values to be adjusted during the update loop.
A short introduction to particle systems in Unity
The Unity Particle System is a tool for creating and controlling dynamic visual effects such as fire, smoke, explosions, and more. It simulates the behavior of individual particles, which can be emitted, move, change color, size, and fade over time, creating effects in real-time.
Adding a new particle system involves adding the Particle System component to a game object. In addition to the built-in particle system, the Visual Effect Graph is a newer, node-based system that is GPU optimized and only runs in URP and HDRP
Built-in particle system component
Empty VFX Graph
Firework Effect
We will be taking a short tour of the built-in particle system by building a firework effect.
What are the parts of a firework? How to break down the effect?
Launching
- In a new scene, create an empty game object named “firework” and add a particle system component.
-
Clicking on the object in the hierarchy should show a preview of the effect in the scene view. If it looks like a bunch of pink squares, you’ll need to assign a material to your effect.
- In your project’s assets, create a new material and select it. In the inspector for the material, set the shader to Universal Render Pipeline > Particles > Unlit
- Select the firework game object in the hierarchy and expand the Renderer section of the particle system component in the inspector. Set the Material field to the material you just created. URP should also come with a default ParticlesUnlit material that you can use.
-
The particles aren’t going in the right direction, so rotate the system to make the particles move upward. You can either rotate the x-value of the transform by -90 degrees. Or you can expand the Shape section of the particle system and rotate its x-value by -90 degrees.
- Reduce the number of fireworks being launched. In the Emission section of the particle system, lower the Rate over time value to around one or less.
- Increase the launch speed. Change the Start Speed of the particle system to something a bit faster. Also, increase the Gravity Modifier to one. Play with the values until the behavior looks right.
- Now reduce the Start lifetime of the particle so it disappears at about the apex of its trajectory.
- Scale the size of the launcher using the Start Size value. It might be useful to create a default cube somewhere in your scene to get a sense of scale.
Exploding
-
Create another particle system named “explosion”. In addition to adding the particle system to an empty game object. You can also use Game Object > Effects > Particle System
- Open the Shape section of this particle system and change the shape to Sphere. Now the particles will emit outward in all directions.
-
Make it so the particles all emit together. Under the Emission section, change the Rate over Time value to zero and add a new Burst to the burst list. Adjust the Count (even set the count to be randomized).
- Adjust the Start Speed, Start Size, Start Lifetime, Gravity Modifier until you are happy with the effect.
Connecting the two. Sub Emitters
- Select the firework launcher game object and expand the Sub Emitters section of the particle system component. If it’s grayed out, you’ll need to select the check-box next to the name.
- Change Birth to Death and then drag the explosion particle system into the empty slot. When a popup appears, select Yes, reparent to make the explosion a child of the launcher game object.
-
Additionally, change the Inherit property to Color so that the explosion will inherit the color of the launched firework.
- Now the preview should be showing the launch and explosion of the firework.
-
Add random colors to the system. Change the Start Color of the launcher to Random Color. Then click the color swatch and add in a few different colors inside the gradient editor. Selecting the bottom arrow lets you change the color at that position, the top arrow lets you change the alpha value of that position (note: make sure the material you are using in your particle system is set to transparent, otherwise the alpha values will be ignored).
- Now you should see randomized colors for each firework. Try playing around with other settings on the particle system. Color over Lifetime could be used to fade out the explosion. Trails can add some more effects.
What other things could you build? Snow? Fire? Rain? Confetti?