Here's what I did during my masters.
During my first module, we were tasked with learning as much as we could and deciding on a specialization. I focused on various projects that allowed me to explore different aspects of game development with a technical focus. Below are some of the key projects I worked on during my first module:
Since I was learning as much technical design as I could, I started looking into how to optimize code and apply SOLID principles. Specifically, I made use of:
These principles helped me create a more modular and maintainable codebase, which is crucial in game development where complexity can quickly escalate.
Additionally, I started looking into how to optimize the code for performance. I found that using structs instead of classes for certain data types could help reduce memory overhead and improve performance, especially in scenarios where many instances of a type were created.
I also learned how to make use of Addressables in Unity. Addressables is a system in Unity that simplifies the management of assets by allowing developers to load and unload assets dynamically at runtime. It provides an efficient way to handle large amounts of content, optimize memory usage, and reduce build size. Using Addressables, I was able to load assets asynchronously, you can even host assets remotely for better scalability such as updating a game with new puzzles.
By using Addressables, I could load only the assets needed for a specific scene or gameplay moment, reducing memory usage and improving performance.
Another concept I explored was Runtime-ScriptableObjects. In Unity, ScriptableObjects are a powerful tool for storing data independently of scene objects, making them reusable and shareable across different parts of a project. However, traditional ScriptableObjects are static and cannot be modified during runtime.
Runtime-ScriptableObjects extend this functionality by allowing dynamic creation and modification of ScriptableObjects while the game is running. This makes them particularly useful for scenarios such as:
In one of my older projects, I used ScriptableObjects to manage an inventory system. However, I encountered a limitation where the data stored in the ScriptableObjects could not persist or carry over after the game session ended. By exploring Runtime-ScriptableObjects, I learned how to overcome this limitation by dynamically creating and managing inventory data during runtime, ensuring it could be saved and reused effectively.
Finally, I explored the concept of object pooling, which is a design pattern used to manage the reuse of objects to improve performance and reduce memory overhead. Initially, I underestimated its importance, but after deeper exploration, I realized its potential in scenarios involving frequent instantiation and destruction of objects, such as projectiles in a game.
Object pooling operates on two main principles:
To test this, I created a small project where a large number of projectiles were spawned and reused using an object pool. The pool dynamically allocated new objects when needed, using lazy loading to ensure that additional objects were only created when the pool was exhausted. This approach significantly reduced the overhead of frequent instantiation and garbage collection, leading to smoother performance.
Key technical benefits I observed while implementing object pooling:
In the context of game development, object pooling is particularly useful for managing frequently used objects such as bullets, enemies, or particle effects. By implementing this pattern, I gained a deeper understanding of memory management and performance optimization, which are critical aspects of creating efficient and scalable games.
I recreated a flocking simulation inspired by Craig W. Reynolds' 1987 paper, using a distributed behavioral model with three core rules:
These rules create emergent behaviors mimicking flocks or schools. This model was notably used in Disney’s The Lion King for the wildebeest stampede, simulating lifelike herd movement efficiently.
I was reading Procedural Content Generation in Games by Noor Shaker, Julian Togelius, Mark J. Nelson and I found the L-System generation section quite interesting, so I attempted to recreate its rule-based generation approach in Unity along with attempting to generate some simple 3D shapes to visualize the plants.
Procedural content generation using grammar-based techniques for modeling organic structures.
One idea I had while creating this was a game where you controlled the mutations of the plants and the game would be a calm gardening game where the player could control how the plants grew by messing with the rules. Birds would fly in and drop new seeds with their own rules of growth, and the player could mutate them with other plants.
I started by plotting vectors in my notepad (1,0)(1,1)(0,1)(0,0) which would generate a face—they would connect like triangles.
I started to look into how to generate meshes in Unity. I found a few tutorials on how to do this and I was able to create a basic cube, and then I started to look into how to generate more complex shapes like the ones below.
From this basic knowledge of how to plot and connect points, I wanted to see if I could make use of Perlin noise to generate the height offset of lots of faces connected together.
Overall, I enjoyed how the first module allowed for solo learning and experimentation. I delved into optimization techniques, explored flocking behaviors, and experimented with procedural content generation. These projects not only enhanced my technical skills but also showcasses my passion for creating immersive and dynamic game experiences.
I would recommend the university if you're looking to do your master's. All the lecturers were friendly and knowledgeable.