<aside>
💡 💡 (n) indicates a value that is tunable inside the Unity editor
</aside>
Vacuole GPT Prompt
Overview
Vacuole is a single-player dual-stick action game.
The player controls amoebas in a petri dish that is swarming with obstacles, hazards, and dangerous microorganisms.
The player can pick up effects and abilities to empower their amoebas, and the powers can be combined for even more variety!
The goal is to become the largest entity on the petri dish by absorbing smaller microorganisms while avoiding being eaten or killed.
Each level is larger than the last and filled with more and deadlier hazards. How far can the player get?
Similar Games
- Katamari Damaci
- Donut County
- Agar.io
- Fishy! (flash game)
The Game Level
The game takes place inside a circular petri dish that is filled with obstacles and hazards that make the game unpredictable and challenging. A set number of enemies spawn throughout the level, and the player must consume them all to win.
Level Manager Game Object
The Level Manager object is parent to the Petri Dish level, the EnemyManager object, the ObstacleManager object, and the Level Background object
LevelHandler Script
- Handles the level’s play space, difficulty, and objectives
- Sets the size of the Petri Dish and Level Background at the beginning of play
- Increases the size of the next level by a set Growth Factor
- Dynamically adjusts the Petri Dish’s Edge Collider 2D to fit the level size
- Creates up to 100 points for Edge Colliders on larger levels
- Ensures the first and last points have matching coordinates
- Tracks the level number, starting with Level 1
- Ensure the current level number is publicly available for other scripts to reference
- Sets the Difficulty to a value between 1 and 4, influencing various aspects of gameplay.
- Ensure the difficulty level is publicly available for other scripts to reference
- Sets the Consumption Requirement to complete the level based on Difficulty and Level Number
Consumption Requirement = Base Consumption Requirement * (Level Number ^ Level Growth Factor) * (Difficulty ^ Difficulty Growth Factor)
- Marks a level complete when all the Consumption Requirement is met
- Triggers the Level Complete UI flow when a level objective is complete
- Generates a new level after the Level Complete UI flow finishes
- Creates public variables with tooltips:
- MinLevelSize: Defines the smallest possible size for the level's play area.
- MaxLevelSize: Specifies the largest possible size for the level's play area.
PetriDish Prefab
The PetriDish game object handles everything for the game’s petri dish play space. It contains:
Sprite Renderer
- Displays the petri dish image, set to the ‘LevelBackground’ sorting layer
EdgeCollider2D
- Creates a barrier around the edge of the petri dish, to keep game objects inside (on top) of the petri dish sprite
Enemy Manager Game Object
The Enemy Manager handles enemy pooling and spawning logic and parents all enemy objects
SpawnManager script
- Adjusts spawning based on Difficulty and Level Progress
- Spawn Rate: One enemy is enabled from and random enemy spawn pool once every spawn rate.
- Starts at the Base Spawn Rate value at Level 1
- Gets progressively shorter as the level increases with harsher duration reductions at higher difficulties.
Spawn Rate = Mathf.Max(Base Spawn Rate / (1 + (Level Number ^ Level Growth Factor) * (Difficulty ^ Difficulty Growth Factor)), MinSpawnRate)
- Never goes below the Minimum Spawn Rate.
- MaxAllowedActive: Dictates the maximum number enemies allowed on the level at any time
- Starts at the Max Allowed value at Level 1
- Gets progressively larger as the level increases with larger increments at higher difficulties.
Maximum Allowed Active = Mathf.Min(Base Allowed Active + (Level Number ^ Level Growth Factor) * (Difficulty ^ Difficulty Growth Factor), MaxAllowedActive)
- Determines the enemy spawn location depending on whether or not there are active Spawner objects on the level.
- If there are NOT Spawners, enemies spawn at random locations around the level
- If there are Spawners, the random location spawning logic is disabled and enemies spawn at the spawn location
- Determines which Enemy Type list(s) to use, depending on whether or not there are active Spawner objects on the level.
- If there are NOT Spawners, use the SpawnManager’s default EnemyType list
- If there are Spawners, use the Spawner’s EnemyType list
- Each Spawner has its own EnemyType list
- Handles Enemy Type pooling logic
- Each EnemyType list has a dedicated enemy pool
- Each list adds instances of the available enemy types to the spawn pool based on their relative spawnWeight values.
- Stops adding enemies to the pool when the Max Allowed Enemies value is reached
- If the number of enemies in the pool is less than the Max Allowed Active Enemies value once all enemy types in the list have reached their Base Pool Size, continue adding instances of the enemy type until the Max Pool Size is reached.
- It is okay if the number of enemies in the pool is less than the Max Allowed Active Enemies value once all enemy types in the list have reached their Max Pool Size
- Integrates with the ‘PlayerManager’ object to guarantee that:
- Most enemies spawn close to the player’s size, with a mixture of enemies that are larger and smaller
- There is always at least one active enemy that is smaller than the player, and spawns one if there isn’t
- Creates public variables with tooltips for level settings including but not limited to:
Obstacle Manager Game Object
- Randomly places obstacles and hazards around the level
- Creates public variables with tooltips for level settings including but not limited to:
Player Characters
Controls
The player controls two separate amoebas in a circular petri dish environment. The two amoebas can merge into a larger amoeba, which can then split back into its smaller counterparts. When merged, the control system dynamically shifts to manage the combined properties of both amoebas in a single entity.
Technical Implementation
The controls are handled by Unity’s Input System and the ’PlayerManager’ game object. Review the screenshot below to see how the Input Actions are set up in the project.

Input Action settings
Camera