Learning Design Patterns with Unity: Learn the secret of popular design patterns while building fun, efficient games in Unity 2023 and C#
()
Harrison Ferrone
Harrison Ferrone was born in Chicago, IL. Most days, you can find him creating instructional content for LinkedIn Learning or trying to learn something new. He holds various fancy looking pieces of paper from the University of Colorado at Boulder and Columbia College Chicago, and despite being a proud alumnus, most of these are stored in a basement somewhere. After a few years as an iOS developer at small start-ups, and one Fortune 500 company, he fell into a teaching career and never looked back. Throughout all this, he's bought many books, acquired a few cats, worked abroad, and continually wondered why Neuromancer isn't on more course syllabi
Related to Learning Design Patterns with Unity
Related ebooks
Mastering Java Design Patterns: Unlock the Secrets of Expert-Level Skills Rating: 0 out of 5 stars0 ratingsProfessional Java EE Design Patterns Rating: 0 out of 5 stars0 ratingsDesign Patterns in Practice: Unlock the Secrets of Expert-Level Skills Rating: 0 out of 5 stars0 ratingsThe Easiest Way to Learn Design Patterns Rating: 0 out of 5 stars0 ratingsDesign Patterns Made Easy: A Practical Guide with Examples Rating: 0 out of 5 stars0 ratingsJava 8 to 21: Explore and work with the cutting-edge features of Java 21 (English Edition) Rating: 0 out of 5 stars0 ratingsObject-Oriented Analysis: Using Design Patterns Rating: 0 out of 5 stars0 ratingsMastering C++ Design Patterns: Create Efficient and Scalable Code Rating: 0 out of 5 stars0 ratingsMastering Design Patterns with Python: Essential Techniques for Efficient Software Development Rating: 0 out of 5 stars0 ratingsMastering Python Design Patterns for Scalable Applications: Unlock the Secrets of Expert-Level Skills Rating: 0 out of 5 stars0 ratingsEssential Design Patterns in Java: Mastering Core Concepts and Practical Applications Rating: 0 out of 5 stars0 ratingsDesign Patterns in Java: From Basics to Expert Proficiency Rating: 0 out of 5 stars0 ratingsObject-Oriented Python: Master OOP through Game Development and GUI Applications Rating: 0 out of 5 stars0 ratingsMastering Python Design Patterns: Craft essential Python patterns by following core design principles Rating: 0 out of 5 stars0 ratingsAdvanced JavaScript Design Patterns Rating: 0 out of 5 stars0 ratingsMastering JavaScript for Game Development: Crafting Unique Experiences Rating: 0 out of 5 stars0 ratingsArchitectural Metapatterns: The Pattern Language of Software Architecture Rating: 0 out of 5 stars0 ratingsSoftware Patterns Made Easy Rating: 0 out of 5 stars0 ratingsUnity from Zero to Proficiency (Beginner): Unity from Zero to Proficiency, #2 Rating: 5 out of 5 stars5/5Learn C# Programming by Creating Games with Unity Rating: 0 out of 5 stars0 ratingsLearning Construct 2 Rating: 0 out of 5 stars0 ratingsA Quick Guide to Procedural Levels with Unity: Quick Guides, #2 Rating: 5 out of 5 stars5/5Mastering Unreal Engine 4.X Rating: 0 out of 5 stars0 ratingsHands-On Unity Game Development: Unlock the power of Unity 2023 and build your dream game Rating: 0 out of 5 stars0 ratingsA Quick Guide to Card Games with Unity: Quick Guides, #5 Rating: 0 out of 5 stars0 ratingsAdvanced LibGDX: Engineering Complex Java Games: LibGDX series Rating: 0 out of 5 stars0 ratingsMastering the Craft: Unleashing the Art of Software Engineering Rating: 0 out of 5 stars0 ratingsA Quick Guide to c# with Unity: Quick Guides, #1 Rating: 5 out of 5 stars5/5HoloLens Blueprints Rating: 0 out of 5 stars0 ratingsMaster Procedural Generation with Unity and C# Rating: 0 out of 5 stars0 ratings
Programming For You
Coding All-in-One For Dummies Rating: 4 out of 5 stars4/5SQL QuickStart Guide: The Simplified Beginner's Guide to Managing, Analyzing, and Manipulating Data With SQL Rating: 4 out of 5 stars4/5Python Data Structures and Algorithms Rating: 5 out of 5 stars5/5SQL All-in-One For Dummies Rating: 3 out of 5 stars3/5Excel 101: A Beginner's & Intermediate's Guide for Mastering the Quintessence of Microsoft Excel (2010-2019 & 365) in no time! Rating: 0 out of 5 stars0 ratingsExcel : The Ultimate Comprehensive Step-By-Step Guide to the Basics of Excel Programming: 1 Rating: 5 out of 5 stars5/5HTML in 30 Pages Rating: 5 out of 5 stars5/5Python: For Beginners A Crash Course Guide To Learn Python in 1 Week Rating: 4 out of 5 stars4/5Python: Learn Python in 24 Hours Rating: 4 out of 5 stars4/5Learn to Code. Get a Job. The Ultimate Guide to Learning and Getting Hired as a Developer. Rating: 5 out of 5 stars5/5Python Programming : How to Code Python Fast In Just 24 Hours With 7 Simple Steps Rating: 4 out of 5 stars4/5Microsoft Azure For Dummies Rating: 0 out of 5 stars0 ratingsCoding with JavaScript For Dummies Rating: 0 out of 5 stars0 ratingsLearn PowerShell in a Month of Lunches, Fourth Edition: Covers Windows, Linux, and macOS Rating: 5 out of 5 stars5/5Algorithms For Dummies Rating: 4 out of 5 stars4/5Spies, Lies, and Algorithms: The History and Future of American Intelligence Rating: 4 out of 5 stars4/5JavaScript All-in-One For Dummies Rating: 5 out of 5 stars5/5Linux: Learn in 24 Hours Rating: 5 out of 5 stars5/5The Absolute Beginner's Guide to Binary, Hex, Bits, and Bytes! How to Master Your Computer's Love Language Rating: 5 out of 5 stars5/5Coding All-in-One For Dummies Rating: 0 out of 5 stars0 ratingsPYTHON PROGRAMMING Rating: 4 out of 5 stars4/5
Reviews for Learning Design Patterns with Unity
0 ratings0 reviews
Book preview
Learning Design Patterns with Unity - Harrison Ferrone
Contents
Preface
Who this book is for
What this book covers
To get the most out of this book
Get in touch
Priming the System
A word about software architecture
What are design patterns?
The Gang of Four
Pattern categories
Creational patterns
Behavioral patterns
Structural patterns
Why use design patterns?
When to use design patterns
Common pitfalls
About the example projects
Client code
Old vs new input system
Art assets
Summary
Further reading
Managing Access with the Singleton Pattern
Technical requirements
Breaking down the pattern
Diagramming the pattern
Pros and cons
Updating a MonoBehavior into a persistent singleton
Persisting the singleton between scenes
Testing for duplicate managers
Creating a generic singleton
Adding thread safety to the generic singleton
Thread locking during lazy instantiation
Creating singletons as ScriptableObjects
Summary
Further reading
Spawning Enemies with the Prototype Pattern
Technical requirements
Breaking down the Prototype pattern
Diagraming the pattern
Pros and cons
Implementing shallow and deep object copying
Adding a prototype interface
Making shallow object copies
Making deep object copies
Adding a prototype factory
Cloning prefabs
Creating a generic prototype component
Summary
Further reading
Join our community on Discord
Creating Items with the Factory Method Pattern
Technical requirements
Breaking down the Factory Method pattern
Diagramming the pattern
Pros and cons
Declaring our inventory products
Adding a product interface
Creating concrete products
Working with different factory class variations
Adding an abstract factory class
Building a concrete factory
Creating a concrete factory class
Building a parameterized factory
Creating a parameterized factory class
Scaling factories with reflection and LINQ
Adding GameObjects to the mix
Updating the Item class
Updating the Abstract Creator class
Updating the concrete factory
Updating the reflection factory
Extending products and factories with Scriptable Objects
Summary
Further reading
Join our community on Discord
Building a Crafting System with the Abstract Factory Pattern
Technical requirements
Breaking down the Abstract Factory pattern
Diagramming the pattern
Pros and cons
Creating related but independent products
Scripting product interfaces
Adding concrete products
Creating abstract and Concrete Factory classes
Writing a client class using only interfaces
Creating related and dependent products
Writing dependent product abstract classes
Creating concrete products
Adding abstract and Concrete Factory classes
Updating the client
Optional factory variations
Parameterized factories
Creating a factory of factories
Summary
Further reading
Join our community on Discord
Assembling Support Characters with the Builder Pattern
Technical requirements
Breaking down the Builder pattern
Diagramming the pattern
Pros and cons
Creating a base ally and builder interface
Scripting the product class
Declaring a common builder interface
Adding concrete builders
Using a director class
Integrating GameObjects
Transitioning to a Fluent Builder structure
Summary
Further reading
Managing Performance and Memory with Object Pooling
Technical requirements
Breaking down the Object Pool pattern
Diagramming the pattern
Pros and cons
Writing an Object Pool class
Creating objects and filling the pool
Retrieving pooled objects
Releasing pooled objects
Resetting pooled objects
Object Pooling customizations
Queues over lists
Thread-safe pools
Managing different pooled objects
Leveraging Unity’s ObjectPool class
Summary
Further reading
Join our community on Discord
Binding Actions with the Command Pattern
Technical requirements
Breaking down the Command pattern
Diagramming the pattern
Reusable versus single-use commands
Pros and cons
Building a basic Command structure
Creating reusable commands
Adding a receiver
Adding an invoker class
Using an input listener
Updating the client
Creating coupled commands
Implementing an undo/redo system
Stacking commands
Adding an undo feature
Adding a redo feature
Confirming and clearing commands
Summary
Further reading
Join our community on Discord
Decoupling Systems with the Observer Pattern
Technical requirements
Breaking down the Observer pattern
Diagramming the pattern
Pros and cons
Creating a basic Observer structure
Writing the abstract base objects
Making the UI an observer
Subscribing observers and publishing events
Pattern strategies and optimizations
Choosing a communication strategy
Listening for different state changes
Cleaning up hanging resources
Using C# event types
Delegates and events
Updating to Action types
UnityEvents and the Inspector
Adding Unity events
Adding UnityEvent parameters
Persistent versus non-persistent events
The final boss – drag-and-drop system
Writing a ScriptableObject event
Creating listeners
Creating ScriptableObject event assets
Invoking the SOEvent
Connecting the system
Performance considerations
Picking the right implementation
Summary
Further reading
Join our community on Discord
Controlling Behavior with the State Pattern
Technical requirements
Breaking down the State pattern
A little automata theory
Diagramming the pattern
Pros and cons
Creating a turn-based battle system
Defining abstract and base states
Creating a state machine
Protecting transitioning states
Subclassing state machines
Creating concrete states
Base state
Setup state
Player state
Enemy state
Ending state
Putting it all together
Initializing concrete states
Updating the client
Using a hierarchical state machine
Adapting for concurrent state machines
Unrelated concurrent states
Related concurrent states
Storing state history
Pushing new states
Reverting to previous states
Summary
Further reading
Adding Features with the Visitor Pattern
Technical requirements
Breaking down the Visitor pattern
Diagramming the pattern
Pros and cons
Creating a save system
Structuring the interfaces
Adding a concrete visitors
Adding concrete elements
Adding an object structure
Working with composite elements
Accounting for selective visitation
Summary
Further reading
Join our community on Discord
Swapping Algorithms with the Strategy Pattern
Technical requirements
Breaking down the Strategy pattern
Diagramming the pattern
Pros and cons
Creating a sorting system
Defining a strategy interface
Adding concrete strategies
Creating a context
Optimizing your strategies
Adding interchangeable strategies
Using default strategies
Strategies the Unity way
Upgrading to ScriptableObjects
Summary
Further reading
Join our community on Discord
Making Monsters with the Type Object Pattern
Technical requirements
Breaking down the Type Object pattern
Diagramming the pattern
Pros and cons
Creating monsters
Adding a Type Object
Configuring monsters
Optimization, inheritance, and behavior
Controlling allocation and initialization
Adding parent type objects
Sharing behavior isn’t easy
Creating ScriptableObject monsters
Summary
Further reading
Taking Data Snapshots with the Memento Pattern
Technical requirements
Breaking down the Memento pattern
Diagramming the pattern
Pros and cons
Creating and restoring data snapshots
Adding the memento class
Setting up the caretaker
Updating the originator
Wiring up the client
Working with MonoBehaviours
Memento pattern variations
Storing memento history
Bundling originator and caretaker
Managers and ScriptableObject snapshots
Persisting data
Summary
Further reading
Join our community on Discord
Dynamic Upgrades with the Decorator Pattern
Technical requirements
Breaking down the Decorator pattern
Diagramming the pattern
Pros and cons
Building a simple Decorator
Adding a Component interface
Creating a concrete Component
Using a base Decorator
Building a concrete Decorator
Chaining multiple Decorators
Adding customized behaviors
Using ScriptableObject Decorators
Static vs dynamic decoration in action
Summary
Further reading
Join our community on Discord
Converting Incompatible Classes with the Adapter Pattern
Technical requirements
Breaking down the Adapter pattern
Diagramming the pattern
Pros and cons
Building a controller adapter
Defining a target
Adding the class adapter
Creating an object adapter class
Mapping properties in separate hierarchies
Summary
Further reading
Simplifying Subsystems with the Façade Pattern
Technical requirements
Breaking down the Façade pattern
Diagramming the pattern
Pros and cons
Building a subsystem Façade
Defining subsystem objects
Initializing subsystems
Adding a public Façade method
Adding multiple Façade methods
Upgrading Façades
Summary
Further reading
Join our community on Discord
Generating Terrains with the Flyweight Pattern
Technical requirements
Breaking down the Flyweight pattern
Diagramming the pattern
Pros and cons
Creating shareable terrains
Adding a Flyweight interface
Extracting extrinsic state
Building a concrete Flyweight
Adding a Flyweight factory
Working with unshared Flyweights
Upgrading to ScriptableObjects
Flyweight or Type Object?
Summary
Further reading
Global Access with the Service Locator Pattern
Technical requirements
Breaking down the Service Locator pattern
Diagramming the pattern
Pros and cons
Creating services and contracts
Logging and saving contracts
Planning for missing services
Building a Service Locator class
The Null Object pattern
Adding a generic solution
Extending locator functionality
Initializing services
Explicitly registering services
Unregistering services
A word on scope
Singleton Service Locators
Grouping services
A service for every level
Summary
Further reading
Join our community on Discord
The Road Ahead
SOLID principles and you
The patterns left out (but not forgotten)
Resourceful resources
Getting involved
Summary
Other Books You May Enjoy
Index
Landmarks
Cover
Index
Learning Design Patterns with Unity
Learn the secret of popular design patterns while building fun, efficient games in Unity 2023 and C#
Harrison Ferrone
Learning Design Patterns with Unity
Copyright © 2024 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Senior Publishing Product Manager: Larissa Pinto
Acquisition Editor – Peer Reviews: Gaurav Gavas
Project Editor: Meenakshi Vijay
Content Development Editor: Tanya D’cruz
Copy Editor: Safis Editing
Technical Editor: Tejas Mhasvekar
Proofreader: Safis Editing
Indexer: Pratik Shirodkar
Presentation Designer: Rajesh Shirsath
Developer Relations Marketing Executive: Sohini Ghosh
First published: May 2024
Production reference: 2080724
Published by Packt Publishing Ltd.
Grosvenor House
11 St Paul’s Square
Birmingham
B3 1RB, UK.
ISBN 978-1-80512-028-5
www.packt.com
Contributors
About the author
Harrison Ferrone was born in Chicago, Illinois, and was raised all over the U.S. He’s worked at Microsoft, PricewaterhouseCoopers, and a handful of small start-ups, but most days you can find him creating instructional content for LinkedIn Learning or working on new projects. He holds various fancy-looking pieces of paper from the University of Colorado Boulder and Columbia College Chicago. Despite being a proud alumnus, these are stored in a basement somewhere. After a few years as a full-time iOS and Unity developer, he fell into a teaching career and never looked back. Throughout all this, he’s bought many books, been owned by several cats, worked abroad, and continually wondered why Neuromancer isn’t on more course syllabi.
Completing this book wouldn’t have been possible without the loving support of Kelsey, my wife and partner in crime on this journey.
About the reviewers
Charles Haché, also known as Oz, is a seasoned game development teacher with extensive experience at both the high school and university levels. As a technical mentor for graduates and individuals seeking to upskill, he specializes in Unity, C# OOP, architecture, design patterns, VR, AR, instructional design, and leadership. In addition to his teaching roles, Oz has contributed to various game development projects and has been instrumental in shaping curricula that bridge the gap between academic theory and practical application. He has worked with several esteemed organizations, including the University of Victoria as a Unity Certified Instructor, Mastered Studios Inc. as a technical mentor, and Pearson as a subject mattter expert in Unity. His expertise has been sought after for technical reviews and consultations on several notable publications within the game development community.
In working on this book, I would like to extend my heartfelt gratitude to my wife, Kari, for all the support she has given me over the past 12 years. I look forward to sitting on a porch with her, holding hands, now that this book is finished.
Luiz Henrique Bueno, also known as Rick Good, began his career in Brazil, focusing on smart home and IoT projects. This laid the groundwork for his expertise in software architecture and design patterns, leading to proficiency across iOS, macOS, Windows, and XR platforms. By 2016, he had become one of Brazil’s first Unity Certified Developers, showcasing his depth in game development. After moving to the USA in 2017, he founded Toodoo Studio, where he successfully launched several game titles, including Global Destruction VR, Blondie on the Road, Thomas’ Tales, and Food Chase, using Unity and Unreal Engine. His contributions extend to authoring and technically reviewing Unity books and creating educational content on Unity and Unreal development. His technical skills span from C++ and C# to Swift, React, and Node.js. He has ventured into XR applications for Apple Vision Pro and Meta Oculus devices, continuing to push the boundaries of interactive technology. For a closer look at his projects and achievements, visit his portfolio at https://rickgood.me.
Join our community on Discord
Join our community’s Discord space for discussions with the author and other readers:
https://packt.link/gamedevelopment_packt
Preface
Design patterns have been around for a very, very long time (decades in fact), lighting the way through dark and troubled waters where scale, flexibility, access, communication, and optimization try to capsize your best coding efforts at every turn. You’ll see these concepts taught and embedded in most, if not all, Computer Science curriculums around the world, but they’re conspicuously missing from many a young game programmers toolkit (mine included when I first started out).
Maybe these skills are traditionally taught by more experienced developers and mentors over the course of a programmer’s career. Maybe games are supposed to be fun to make, leaving the more serious work to the engineers who specialize in creating large accounting systems, traffic monitoring algorithms, or global trading platforms. Maybe this skill gap has simply been overlooked in favor of game mechanics and amazing animations (not that those aren’t important bits – we’d be nowhere without them).
Whatever the reason, we need to break the current pattern of sending young developers off into the wilds with swords but no potions and start training for reality – a reality where games are still only play, but the underlying game systems need to be just as complex, flexible, and well architected as the software products we use in our daily lives!
Who this book is for
I’m going to daringly assume that you’re a programmer, hobbyist, software engineer, game designer, or unicorn hybrid of all the above. You might be looking to advance your C# and/or game programming knowledge, getting ready for a promotion, or just trying to make your code more reusable, flexible, and professional.
The goal of this book isn’t to specifically teach you how to build applications, games, the ins-and-outs of the Unity engine, or even C# for that matter; it’s to teach you how to think, problem-solve, and implement systems in your code. C# is a great Object-Oriented language,
Unity is an engaging visual environment, and games are a fun way to learn, but these are all tools for us to learn and design better systems (with the help of design patterns).
Even though design patterns aren’t for complete programming beginners, once you have a basic competency in C# and Unity, it’s never too early to start thinking and learning about good software architecture. Chances are that the way you’re writing code right now could use a boost of optimization, flexibility, and efficiency. And that’s why you’re here, right?
What this book covers
Chapter 1, Priming the System, starts off with a brief trip into software architecture, software design, and design pattern categories, all while getting comfortable with the why and when of implementing these solutions. We’ll also go over the common pitfalls of using design patterns for the first time and the example projects used throughout the book.
Chapter 2, Managing Access with the Singleton Pattern, begins by laying the groundwork for uses-cases where globally accessible classes are needed (like persistent game managers) and moves on to generic singleton classes, thread-safety, and converting singletons into ScriptableObjects.
Chapter 3, Spawning Enemies with the Prototype Pattern, takes a deep dive into efficiently creating objects without the memory overhead by copying instead of instantiating new instances. We’ll also cover the differences between shallow and deep object copying in C#, clone prefab objects, and build a generic cloning script component.
Chapter 4, Creating Items with the Factory Method Pattern, introduces the concept of object factories that can produce a variety of products, different factory variations we can use to make our code more efficient and flexible, and scale factory production with Reflection and LINQ.
Chapter 5, Building a Crafting System with the Abstract Factory Pattern, details the process for creating factories of factories, working with families of related and independent (or dependent) products, and finally exploring Abstract Factory variations for niche scenarios.
Chapter 6, Assembling Support Characters with the Builder Pattern, delves into an assembly line approach to creating complex objects using the same construction processes to pump out different products. We’ll also add GameObjects to the mix and use the fluent Builder pattern variation for cleaner code.
Chapter 7, Managing Performance and Memory with Object Pooling, introduces the concept of recycling batches of objects for reuse instead of creating new instances from scratch while incorporating thread-safety and Unity’s own generic
ObjectPool
class.
Chapter 8, Binding Actions with the Command Pattern, starts with an overview of actionable requests and pre-packaging everything a command may need to be executed. We’ll also dive into the differences between coupled and uncoupled commands, their respective use cases, and how to build a complete undo/redo system from scratch.
Chapter 9, Decoupling Systems with the Observer Pattern, takes a more in-depth look at communication strategies between objects, how to effectively separate message senders from receivers, and the performance pros and cons of using native C# events versus Unity events.
Chapter 10, Controlling Behavior with the State Pattern, dives into the concept of managing an objects’ state, transitioning between states, and the basic theory behind state machines. We’ll also explore different configurations of state machines, including Finite state machines, Hierarchical state machines, and Concurrent state machines, as well as how to track and store state history.
Chapter 11, Adding Features with the Visitor Pattern, gets you ready to add new behaviors to existing objects without changing the underlying object in any way by creating a simple saving system. We’ll also learn how to deal with composite elements (objects with children) and how to convert our save system to use ScriptableObjects.
Chapter 12, Swapping Algorithms with the Strategy Pattern, explores how to configure classes and objects with interchangeable behaviors (or algorithms) at runtime by building a simple turn-based battle team example. We’ll also learn how to optimize these strategies for efficiency and update them to use ScriptableObjects.
Chapter 13, Making Monsters with the Type Object Pattern, takes a deep dive into separating common data that a group of related objects share and then creating different configurations of those objects with the least amount of classes using a flat hierarchy. We’ll also look at memory allocation and inheritance optimizations and learn how to incorporate ScriptableObjects as configurable data containers.
Chapter 14, Taking Data Snapshots with the Memento Pattern, introduces a system for storing, managing, and restoring an object’s internal state at any point in time using data snapshots without breaking the object’s encapsulation by building a character builder UI example.
Chapter 15, Dynamic Upgrades with the Decorator Pattern, offers solutions for dynamically adding behaviors to existing objects without subclassing, making a completely optional opt-in system for new upgrades and features.
Chapter 16, Converting Incompatible Classes with the Adapter Pattern, dives into creating shared interfaces for two or more classes that aren’t part of any shared hierarchies to work together. We’ll also touch on two variations (class and object adapters) and how to map properties in mismatched hierarchies.
Chapter 17, Simplifying Subsystems with the Façade Pattern, details a common solution for creating a wall between client code and complex (and often interdependent) subsystems by creating a simple auto-save feature. We’ll also get hands-on experience with adding multiplefaçade methods for clients to access and talk about creating abstract façade classes for certain scenarios.
Chapter 18, Generating Terrains with the Flyweight Pattern, introduces the concept of shareable state, which makes object creation (especially in large quantities) more computationally efficient if objects don’t have to store duplicate data. We’ll also discuss adding factories to this design pattern and how to correctly chose between the Flyweight and Type Object patterns.
Chapter 19, Global Access with the Service Locator Pattern, details a centralized solution for storing and locating systems in your projects that need to be globally accessible. Like singletons, these services may need to be persistent and accessible from anywhere, which means putting them into a single registry not only makes initialization easier, but it also makes them less prone to abuse.
Chapter 20, The Road Ahead, finishes with a look at the SOLID design principles, the design patterns we didn’t cover, and resources to take your programming skills to the next level.
To get the most out of this book
My north star is always making my content accessible to as many people as possible, which means I naturally try and keep prerequisites and barriers to entry fairly low or non-existent. However, design patterns are an intermediate programming topic, which means you need some foundational competencies to get going and feel confident with the material being presented.
Whatever brought you here, we need to lay out some basic requirements for getting the best possible experience from reading this book, so we’re all on the same page. Here’s what you’ll need before getting started:
Know how to write C# and its basic language components like variables, types, access modifiers, and control flow.
Understand and use Object-Oriented Programming concepts like classes, objects, interfaces, generics, events, delegates, inheritance, and encapsulation.
Be comfortable with Unity and the Unity editor, including navigation, creating scripts, and adding objects to the scene. You should also be comfortable with coroutines and basic Unity events like Awake, Start, and Update.
I don’t want all of this to sound discouraging, so just know that if you’ve been playing around with Unity and C# for a few months, maybe watched some tutorials, or even made a simple playable prototype or two - you can absolutely continue reading. This book is a reference, which means you’ll likely need to revisit chapters more than once to get things cemented in your mind. Don’t feel obligated to read the book in sequence either – the right tool for the job is the mainstay of everything you’ll learn here.
You’ll also need the current version of Unity installed on your computer—2023 or later is recommended. All code examples have been tested with Unity 2023.1 and should work with future versions without issues.
Before starting, check that your computer setup meets the Unity system requirements at https://docs.unity3d.com/2023.1/Documentation/Manual/system-requirements.html.
Download the example code files
The code bundle for the book is hosted on GitHub at https://github.com/PacktPublishing/C-Design-Patterns-with-Unity-First-Edition. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
Download the color images
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://packt.link/gbp/9781805120285.
Conventions used
There are a number of text conventions used throughout this book.
Code In Text
: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. For example: "
Manager.cs
stores our score and loads the next scene."
A block of code is set as follows:
using
System.Collections;
using
System.Collections.Generic;
using
UnityEngine;
public
class
Item
:
MonoBehaviour
{
void
OnCollisionEnter
(
Collision collision
)
{
if
(collision.gameObject.tag ==
Player
){
// 1
Manager.Instance.score++; Destroy(
this
.gameObject); Debug.Log(
Item collected!
); } } }
When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:
public
class
Item
:
MonoBehaviour
{
void
OnCollisionEnter
(
Collision collision
)
{
if
(collision.gameObject.tag ==
Player
) {
// 1
GenericManager
.Instance.score++; Destroy(
this
.gameObject); Debug.Log(
Item collected!
); } } }
Bold: Indicates a new term, an important word, or words that you see on the screen. For instance, words in menus or dialog boxes appear in the text like this. For example: "Navigate to Assets | Scenes, and double-click on SplashScreen."
Warnings or important notes appear like this.
Tips and tricks appear like this.
Get in touch
Feedback from our readers is always welcome.
General feedback: Email
and mention the book’s title in the subject of your message. If you have questions about any aspect of this book, please email us at
.
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you reported this to us. Please visit http://www.packtpub.com/submit-errata, click Submit Errata, and fill in the form.
Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at
with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit http://authors.packtpub.com.
Share your thoughts
Once you’ve read Learning Design Patterns with Unity, we’d love to hear your thoughts! Please click here to go straight to the Amazon review page for this book and share your feedback.
Your review is important to us and the tech community and will help us make sure we’re delivering excellent quality content.
Download a free PDF copy of this book
Thanks for purchasing this book!
Do you like to read on the go but are unable to carry your print books everywhere?
Is your eBook purchase not compatible with the device of your choice?
Don’t worry, now with every Packt book you get a DRM-free PDF version of that book at no cost.
Read anywhere, any place, on any device. Search, copy, and paste code from your favorite technical books directly into your application.
The perks don’t stop there, you can get exclusive access to discounts, newsletters, and great free content in your inbox daily.
Follow these simple steps to get the benefits:
Scan the QR code or visit the link below:
https://packt.link/free-ebook/9781805120285
Submit your proof of purchase.
That’s it! We’ll send your free PDF and other benefits to your email directly.
1
Priming the System
As programmers, our job is to design, build, and integrate software features into cohesive products that are useful and hopefully bring joy to our users. And somewhere in all of that, the software has to work. Our job can be anything from building a login feature or networking layer to a subscription and payment portal. In games, we’re thinking of moving a playable character, building an adaptive AI enemy, or adding a random level generator. The big idea that should pop out at you is that these elements don’t exist in a vacuum. In fact, they tend to wither and die of boredom if they’re not connected to each other.
When you think of the code powering your applications and games, you’re thinking about a collection of systems built around specific features or mechanics, but more importantly, around specific problems that come with making those features work as expected. If I could manage it, I’d have the word systems jump off the page and do a little dance to get your attention, because that’s what this entire book is about: games (and applications) are made up of systems – the more these systems grow and interact with each other, the more complicated things get.
Systems may not be anything new to you, and they’re certainly not new to the programming industry, but there are problems that you’ll repeatedly run into that are directly related to systems running and interacting. And that’s really what I want to drive home before we get started: design patterns provide reusable solutions to problems we face in our everyday software lives and offer a common vocabulary for understanding and talking about best practices.
Now the real work starts – how do we identify the parts of our code that could benefit from a design pattern? How does all this relate to software architecture? How can I adapt these patterns for game development in Unity?
These are big questions, which is why we’re spending this first chapter getting a holistic feel for the following topics:
Software architecture vs software design
Design patterns and the categories they belong to (creational, structural, and behavioral)
Why use design patterns at all?
When to use design patterns
Common pitfalls
Starter projects for this book
By the end of the chapter, you’ll have the necessary foundation to dive into design pattern implementations and a big-picture view of the flexibility, reusability, and structure they can add to your projects. But first, let’s make sure you know what to expect from this book and that you’re coming to the table with the prerequisites for getting the most out of the experience.
At the time of writing, all chapter examples and project files were built using Unity 2023.1.5f1. Unity is the visual tool we’re using to make the learning process more inviting, but the bones of the design pattern content are still 100% applicable to C# projects. The main differences that come into play between Unity, C#, and design patterns are how objects are created (new classes vs MonoBehaviours) and assembled (inheritance vs GameObjects and Components). Don’t worry, we’ll cover these variations in each pattern. Learning how each design pattern works as a system doesn’t depend on a specific platform or language – it’s all problem-solving skills!
A word about software architecture
Software architecture is a big topic and shouldn’t be confused with software design even though they both deal with patterns.
When we talk about architectural patterns, we’re talking about big-picture solutions to problems that are typically focused on how multiple components work together at the application level, as well as conventions, best practices, and principles that guide the overall development process. When we talk about software design patterns, we’re talking about problems that crop up when you’re building those internal components. Figure 1.1 provides a simplified example of the key difference we’re talking about: Process A is made up of multiple internal components (the software design portion) while managing and organizing how these internal components fit together (the architectural portion).
Figure 1.1: Example diagram of software architecture vs design
Clear as mud? OK, let’s take a more relatable example: if we think about building a house, the architectural patterns are focused on how the entire house fits together and how the component parts (electrical, plumbing, insulation, etc.) come together into a functioning structure you can live in. Think LEGO (because that always helps me): architectural patterns deal with problems affecting the overall structure you’re building, while design patterns focus on the individual LEGO blocks that make up the final structure. You ideally need both types of solutions in a great application or game, but they solve fundamentally different problems, which is why I bring this distinction up so early in our journey. We’ll be focused on the software design aspect of things, but you can (and should) continue your journey into architectural waters after or in conjunction with this book.
In your everyday life, when you open Twitter (or whatever app you go to first thing in the morning), you’re involved in what’s called the Client-Server architectural pattern – the client (the app on your phone) consumes information from a server somewhere in a basement and displays it to you in a way you can understand. But it’s not concerned with how the app remembers your login credentials or uses face recognition to log you in. Those are software design problems because they focus on the internal features of the application.
Before we get to the why, when, and how of design patterns, we need to agree on a basic understanding of what good software design is to see the benefits of design patterns. Books on software design are everywhere. Amazon thinks you want them, and your co-workers probably have a few gathering dust on their desks right now. Hell, your computer monitor might be sitting on a few of them at this very moment. This isn’t one of those books.
I like to think of software design as a tool that might make things harder in the moment but easier in the long run, like going to the gym. It’s a pain to use the Stairmaster every day, but being healthy has far-reaching benefits throughout a lifetime. The same is true of approaching a project with an eye to software design. With that in mind, let’s set up a simple definition for ourselves as a kind of guiding light for what we mean by good software design:
A codebase that is flexible, maintainable, and reusable is the product of good software design.
This is easier said than done no matter how well-intentioned you or your team start off developing your game. Decoupling your code can speed up your development process, but it adds overhead and maintenance time. On the other hand, interdependent code can be costly when you want to make changes, big or small. It’s all about balance, even if you can’t have everything you want all the time. Fast, good, or cheap – you can only ever have two.
With a working definition of good software design, we can move on to talking about what design patterns are, how they’re categorized, and how they fit into Unity projects.
What are design patterns?
If I haven’t harped on this point enough, I want you to keep thinking to yourself Design Patterns are systems
over and over. Let’s say that again, design patterns are systems, and systems are designed to solve specific problems. It doesn’t matter if it’s the brake system in your car, the biological systems that run our bodies, or the banking system in Figure 1.2. They’re all systems and they’re all trying to solve a problem or keep their respective system organized and balanced (and sometimes both).
Figure 1.2: Diagram of how bank accounts work using credit and debit
More than anything, design patterns focus on making code more flexible and reusable, two tenets we’ll hammer away at throughout this book. Just keep repeating our mantra every time we dive into a new pattern: design patterns are systems!
The Gang of Four
Back in 1994, a group of four daring engineers banded together to better tackle OOP practices and recurring problems that kept popping up in their programs; Design Patterns: Elements of Reusable Object-Oriented Software written by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides is the product of that team-up. The book covers 23 design patterns split into three categories according to their core functions, with examples written in C++ and Smalltalk. While the book was and continues to be an important resource, these patterns have been adapted and expanded since 1994, leaving some more (and some less) relevant depending on your chosen programming language and environment.
There are also those who have pointed out that a fair few of the patterns are replacements for perceived missing features in the C++ language. However, this argument has never resonated with me when I look at my code in other languages (whether it’s C# or something like Swift) because wearing my systems-thinking glasses has always made me think more critically and write code more intentionally.
You’ve likely heard the phrase Gang of Four
whispered with quiet reverence (or loud and angry fist-shaking, depending on who you’re talking to), but with topics like this, I’ve found it’s best to learn design patterns as a skill before making judgments. There are impassioned programmers on both sides of the aisle, which means getting your hands dirty is the best thing you can do for yourself. A lot of the debate gets lost in theoretical or pedagogical minutiae (and personalities) but the core skillset behind design patterns has always been a useful tool for programming.
Pattern categories
There are three categories that all original design patterns fall into – Creational, Behavioral, and Structural. As with all things, additional patterns have evolved since 1994, resulting in useful patterns that were not included in the original Gang of Four book that we’ll cover on our journey and a few honorable mentions (because we can’t cover every design pattern in a single book).
Before we get into the category details, I feel it’s important to address a problem that crops up at the beginning of most journeys into design patterns – how do I find the right pattern for the problem I’m facing? Do I need to read and memorize every pattern, or is there a better way to navigate this topic?
The answer might surprise you, but no, this isn’t a memorization game and you don’t get extra points for knowing everything about every design pattern – systems thinking is a learned skill, not a closed-book test. It’s almost a detective game: first, knowing what problems each pattern category addresses is super important because it narrows the field you have to search. Second, reading the first few pages of each chapter in the applicable category will show you pretty quickly if you’re in the right place. From there, the more you use design patterns, the more you’ll get a feel for the problems and effective solutions out in the wild. As you’ll see, design patterns offer solutions to well-documented problems, but they’re not set in stone; it’s up to you to adapt them to your project.
Now that we know the basics, let’s dive into the nitty-gritty of each design pattern category and what specific problems they aim to solve.
Creational patterns
Creational patterns deal with creating objects that are uniquely suited to a given situation or use case. More specifically, these patterns deal with how to hide object and class creation logic, so the calling instance doesn’t get bogged down with the details. As your object and class creation needs become more complex, these patterns will help move you away from hardcoding fixed behaviors toward writing smaller behavior sets that you can use to build up more complex features (think LEGO). A good creational pattern black-boxes the creation logic and simply hands back a utility tool to control what, who, how, and when an object or class is created.
The creational patterns we’ll cover are listed in the following table:
Table 1.1: List of creational design patterns with descriptions
Behavioral patterns
Behavioral patterns are concerned with how classes and objects communicate with each other. More specifically, these patterns concentrate on the different responsibilities and connections objects have with each other when they’re working together. Like structural patterns, behavioral patterns use inheritance to divvy up behaviors between classes, which gives you the freedom to let go of any white-knuckled control flow responsibilities and focus on how objects can work together.
The behavioral patterns we’ll cover are listed in the following table: