This repository contains the source code for a series of articles about writing cleaner and scalable code in Unity. The series is designed to help developers improve their coding practices by applying object-oriented design principles, SOLID principles, and design patterns. You can read the full series of articles at Unity Discussions .
- Unity 6000.0.17f1 or higher
- Basic understanding of C# and Unity
This repository contains a 'Project' folder, which can be opened in Unity Hub, and a 'Scripts for Articles' folder, where you can find the scripts as they evolve with each article. This setup makes it easy to see how each script changes after refactoring or extending its functionality.
- Clone or download this repository,
- Open the "Project" folder in Unity Hub,
- Search for "_Scripts" folder and inside it you will find folders called "Article 1" (up to "Article 5"),
- Each folder contains "Start" and "Result" folder where you will find a unity scene that you can open and all the scripts used in it
It contains scripts that I reference in the Article series to make it easier for the readers to follow along. Scripts for each article are placed in separate namespaces ex "Tips.Part_1_Result" or "Tips.Part_1_Start" so that you can follow along with our article series or preview the resuls.
In this article, we refactor the initial project to separate concerns and make the codebase more maintainable. We focus on:
- Single Responsibility Principle (SRP): Breaking down the monolithic
PlayerMonolithic
script into smaller, focused components. - Dependency Inversion Principle (DIP): Introducing abstractions to decouple the
PlayerMonolithic
from specific input implementations. - Strategy Pattern: Implementing different rotation strategies for the player and NPC.
This article demonstrates how to add a jumping mechanic to the game using the State Pattern, ensuring that the code remains clean and maintainable. Key topics covered:
- State Pattern: Separating different states (e.g., Movement, Jump, Fall) and their transitions.
- Transitions: Defining transition rules to manage state changes.
- Interface Segregation Principle (ISP): Extending functionality without modifying existing code.
In this article, we build a modular interaction system using interfaces, enabling scalable and maintainable interactions in the game. Key topics include:
- Creating a modular interaction system: How the IInteractable interface allows us to create a modular and flexible interaction system.
- Polymorphism: How detecting objects of type IInteractable and passing a GameObject enables objects of different classes to be treated as instances of a common interface.
- Creating different interactions: How we utilize the IInteractable interface to create a simple "switch," a pickable weapon, and NPC interactions.
In this article, we will explore the concepts of Composition and Inheritance. We will see how both can be used to make our code architecture more maintainable. Key topics covered:
- Inheritance vs Flexibility: The pros and cons of each approach, and how using both is often the best solution for achieving flexibility and reusability.
- Agent Inheritance hierarchy: Inheritance allows for the reuse of behaviors. We'll examine how creating an Agent inheritance tree helps separate Player, NPC, and EnemyNPC-specific logic into corresponding subclasses.
- Composition-based Movement System: We'll explore how extracting the IAgentMover interface allows us to compose agents with different movement systems (e.g., EnemyNPC uses a NavMesh-based mover).
In the final article of the series, we explore the interface keyword which allows us to create systems that are easily extendable with new behaviors. Topics include:
- IDamagable interface: How different objects can implement the same interface, allowing them to be treated uniformly—demonstrating polymorphism.
- Health system: The Health script implements the IDamagable interface to react to the Attack State.
- Detecting Hit events: Using the Physics.SphereCast() method to detect all objects that can be hit.
- Implementing different Damagable objects: Player, EnemyNPC, and Tree all implement the IDamagable interface, producing different results and feedback when hit.
- Refactoring State pattern: To complete the project, we refactor the StateFactory() method into a separate inheritance hierarchy. This separates the responsibility of state creation from the Agent and its subclasses.
- 3D Game Kit by Unity,
- 3D Game Kit Lite by Unity,
- Food Props by Unity by Unity,
- Starter Assets - ThirdPerson by Unity,
- Animations created using Unity Muse AI,
This project is licensed under the MIT License.