Most of my projects where made in unity. So I am the most comfortable working in unity.
While working on these projects I used the SCRUM-method of workign
Airport Architect is a grid-based airport builder game in which you build and manage your airport, continuously expand it, and become the ultimate Airport Tycoon.
Shadowed Escape is a horror survival game where players explore a dark forest, gathering car parts to repair their vehicle, and evade a sound-sensitive monster that hunts based on noise and light.
Go home is a 3rd person strategy based hack and slash tower defense game where you as the captain must go from planet to planet to collect resources and to get back to your home planet.
When you play the game longer, more characters appear on screen, which can impact performance. To handle this, I created a custom, generic Object Pool script that efficiently manages frequently used objects, like characters or projectiles, by recycling them instead of repeatedly creating and destroying them. This script is a generic object pool that can work with any object type, which helped me learn and apply C# generics for the first time. Using generics allowed me to make the pool versatile and reusable across different game elements, enhancing performance as the game progresses.
To manage employees in the game, I created a dynamic staff management system that includes hiring, firing, and object pooling for efficient resource management. The systTo manage employees in the game, I created a dynamic Staff Management System that handles hiring, firing, and object pooling for efficient resource management. Each employee is represented by an Employee object, and their data is stored in a dictionary, making it easy to track and manage them by their unique ID.
The system utilizes an object pool to manage the creation and recycling of staff objects. When an employee is needed, the pool spawns a new one, and when an employee is no longer required, they are returned to the pool, optimizing memory usage and reducing the overhead of frequent instantiations. The hiring function checks if the player has enough funds before recruiting a new employee, while the firing function releases the employee's resources when they are let go.
The Staff Manager also includes a salary management system that calculates the total salary owed to all employees and processes their payments automatically. I ensured that all aspects of employee management are handled dynamically, with automatic adjustments for changes in the number of employees.
Through building this system, I learned how to manage dynamic objects and resources efficiently within a game, enhancing gameplay by reducing complexity and optimizing performance.
To unlock upgrades and building blocks in the game, the player must complete research tasks. For this, I created a Research Tree that organizes research nodes, where each node represents a different upgrade or technology. To efficiently manage the research process, I developed the RDTreeManager and ResearchNode classes.
The RDTreeManager handles the activation, queuing, and execution of research tasks. It tracks the research nodes, their current state (available, in development, or completed), and manages the queue of tasks. When a node is completed, the manager automatically activates the connected nodes and progresses to the next task in the queue. The manager also ensures that research can be paused, switched, and resumed.
The ResearchNode class represents an individual research task. Each node is linked to other nodes, and when a research task is completed, it unlocks the next set of nodes. The research value is accumulated over time, and once the required value is reached, the node is considered complete. I also added functionality to queue and remove research tasks, ensuring that the research process flows smoothly without interruption.
This system allows for organized and dynamic management of research tasks, ensuring the player can unlock new technologies and progress through the game without feeling overwhelmed by complexity. Through building this, I learned how to create a functional research tree that drives progression and enhances the overall gameplay experience.
To create a suspenseful and dynamic AI system for the monster in the game, I developed a behavior management system that reacts to player actions and environmental factors in real-time. This AI system features a range of monster states—including Roaming, TowardSound, and TowardPlayer—each of which determines how the monster interacts with the player, creating a more immersive horror experience.
In the Roaming state, the monster wanders randomly within a set radius around the player, moving to new locations periodically. This adds a layer of unpredictability, keeping the player on edge. The system includes mechanisms to detect sounds through a microphone input: if the player speaks too loudly or makes noise, the monster enters the TowardSound state and approaches the source of the sound, bringing an extra level of interactivity and tension. Additionally, the monster can detect the player's flashlight or proximity, triggering the TowardPlayer state, where it homes in directly on the player, heightening the threat.
To make this system efficient and realistic, I utilized Unity's NavMeshAgent for smooth pathfinding and character movement, along with an Animator for dynamically adjusting the monster's animations. By leveraging Unity's geometry utility functions, the monster also checks if the player is within its field of view, adding a layer of stealth challenge for the player.
Through building this AI system, I gained experience with advanced state management, real-time audio processing, and navigation control in Unity. This project helped me deepen my understanding of player-centered AI design, enhancing gameplay immersion by making the monster’s behavior feel reactive and lifelike.
This AudioLoudnessDetection class is a core component for creating an interactive enemy AI that responds to the player’s real-time microphone input, adding a unique and immersive element to gameplay. Here’s how it works:
The class captures audio from the player’s microphone, analyzes the loudness, and provides a value that reflects the player's current noise level. This loudness level can be used by the enemy AI to determine the player’s position if they make too much noise, adding a stealth and suspense dynamic.
The Enemy script manages the enemy's health, damage, movement, and knockback. It includes methods for taking damage, reducing health, and applying knockback using a NavMeshAgent for movement and a Rigidbody for physical interactions. The TakeDamage method reduces health, and the Die method destroys the enemy when health reaches zero. The KnockBack coroutine moves the enemy upon being hit, while the enemy's movement speed is controlled via the speed variable. This system ensures realistic combat and enemy behavior, responding to player actions effectively.
The Enemy Controller defines the behavior of an enemy character in a game, using a NavMeshAgent for movement and targeting different routes or the player. It includes a system for dynamically selecting one of several predefined routes, where the enemy moves between checkpoints. The RouteStart method sets up the initial route based on a spawner ID, choosing between different path routes. The TargetRoute methods control the enemy’s movement towards checkpoints along these routes, checking distances to determine when to proceed to the next point. The Attack method allows the enemy to switch to a "Melee" animation when within a stopping distance of the target, otherwise it moves towards the target with a "Walking" animation. Additionally, the FaceTarget method ensures the enemy faces the player or the current target. If the player comes within the lookRadius, the enemy will switch its target to the player. This system enables more immersive and dynamic enemy AI behavior, where the enemy can follow a route and switch to pursuing the player if the player gets too close.
Through this system, I gained hands-on experience with Unity’s NavMeshAgent and pathfinding tools, learning to create AI that navigates through waypoints and adapts to the environment. I implemented a flexible route system that allows enemies to follow different paths, making encounters unpredictable and dynamic. This project also deepened my understanding of modular AI design, where I could easily adjust the behavior and animations of the enemy, enhancing gameplay immersion.
This code is responsible for managing enemy spawning in waves within a game. It utilizes a list of spawn points (spawnerList) and a spawn radius (spawnRadius) to determine where enemies will appear on the map. The enemies are spawned at random intervals (newEnemySpawn) within a specific wave duration (maxTimeInWave), with the wave timer controlling when to trigger the next wave. The EnemySpawn() coroutine handles the process, ensuring that enemies are instantiated at random positions around selected spawners, and the number of enemies spawned (nEnemy) is controlled by the spawn logic. Additionally, the script includes logic for handling different spawn points, allowing for flexibility in how enemies are distributed across the level.