[Unity Notes] Application of Design Patterns in Game Development

Application of Design Patterns in Game Development

Recently, when studying the application of design patterns in game development , I found that they can indeed improve development efficiency, especially in later code adjustment and maintenance.
So I wrote this article and briefly recorded my learning experience, so that I can be inspired when I review it in the future.

Notice

  • This article only summarizes the possible application scenarios of design patterns in game development based on books and Internet materials, and does not explain the principles of design patterns.
  • In practical applications, there are usually cases where multiple design patterns are used in combination. This article is classified by design patterns, and there will be situations where the same usage scenario appears in multiple design patterns.
  • In actual development, some functions may have other implementation methods, or some design patterns may have other application scenarios. The list in this article may be wrong or not comprehensive enough. Your corrections and additions are welcome.

Creational Design Patterns

1. Singleton

The singleton pattern is widely used in game development. The singleton pattern ensures that there is only one instance of a class and provides a global access point to obtain that instance.

scenes to be used illustrate
game manager Responsible for processing the core logic of the game, such as game state, level progress, etc., can be used in combination with appearance mode
audio manager Ditto to the effect
UI manager ditto
Various module managers ditto
data persistence ditto
Online game client Use the singleton mode to limit the number of connections, prevent misuse from generating too many connections, and avoid server-side failure
log tool -

Although the singleton mode is convenient, it should be used as little as possible:
"The singleton mode also violates the principle of opening and closing, because the object obtained through the Instance method is the implementation class rather than the interface class. Therefore, when the design changes or the requirements increase, the program designer It cannot be replaced by other classes, but only the program code in the original implementation class can be changed, so the requirement of closing the modification cannot be met."
—— "Design Patterns and Perfect Game Development"

The singleton pattern can be used to modularize the code. Direct use of the singleton pattern (Singleton) may lead to code confusion and difficulty in maintenance because there is no access restriction.
A full singleton pattern should increase access restrictions. For example, the IOC (Inversion of Control) container is introduced to achieve the effect of a singleton mode with access restrictions by querying the dictionary.
If you compare the game code framework to installation, and the single instance to the connecting lines of several important modules, then introducing an IOC container is equivalent to adding a "cable manager" (many other design patterns also have this function) .
Using the IOC container can easily write code that conforms to the principles of dependency inversion (D) and single responsibility (S).


2. Factory method pattern (Factory Method)

The factory method pattern provides a way to separate the creation and use of objects. By defining a factory interface, subclasses can decide which specific objects to produce.

scenes to be used illustrate
character generation By using the factory method pattern, you can define a role factory interface, and then implement specific factory classes for each role type (such as players, enemies, NPCs, etc.), which can be used with the builder pattern
tool generation You can define a prop factory interface, and then implement specific factory classes for each prop type (such as weapons, armor, consumables, etc.)

3. Abstract Factory Pattern (Abstract Factory)

The Abstract Factory pattern provides an interface for creating a series of related or dependent objects without specifying their concrete classes. The system can decide which group of subclasses to produce according to the current execution environment.

scenes to be used illustrate
resource loading By using the abstract factory pattern, you can create corresponding factory classes for different types of resources, so as to achieve a unified resource loading interface
UI creation Different interface factory classes can be provided to help realize the reuse and customization of UI components
level generation You can create a factory class for different level types (such as forest, desert, city, etc.), which contains different generated content and elements, and you can use the abstract factory pattern when adding new level types
tool generation Ditto to the effect

Abstract factory pattern and factory method pattern

Abstract factory pattern:

  • Abstract Factory Class - *Factory Interface - *Factory Implementation Class - *Produce Products
  • Easy to expand, not easy to modify

Factory method pattern:

  • Factory Interface - Factory Implementation Classes - *Produce Products
  • It is easy to have too many new products and cause the factory to explode

(* indicates that there can be more than one)


4. Builder mode (Builder)

The builder pattern separates the construction process of a complex object from its representation, so that the same construction process can create different object representations. (step by step assembly)

scenes to be used illustrate
character generation Characters can be created in steps and provide different combinations (such as attributes, skills, special effects, AI behaviors, etc.), which enables flexible character creation
level generation The map building process can be broken down into steps, each step is responsible for processing a specific map element (such as terrain, buildings, props, etc.)
tool generation Props and equipment can be created in steps (such as attack power, defense power, durability, etc.), providing flexible combinations

5. Prototype

The Prototype pattern creates new objects by copying existing objects (prototypes), rather than through traditional construction methods.

scenes to be used illustrate
Game resource loading GameObject.Instance in Unity is a prototype pattern

Behavioral Design Patterns

6. State mode (State)

The State pattern allows an object to change its behavior when its internal state changes.

scenes to be used illustrate
role state management Manage role status. For states such as standing, running, jumping, patrolling, attacking, etc., by using the state pattern, the logic and behavior of each state are encapsulated in a separate class, making the switching logic between character states clearer
Game level or scene switching Manage level and scene switching, logic behavior
Game menu and UI state management Such as main menu, setting interface, pause menu, etc. The state mode can simplify the switching logic between these interfaces, making the UI system more modular and easy to maintain

State mode and finite state machine (Finite State Machine, FSM)

The state pattern can be seen as an object-oriented implementation of a finite state machine. State transitions and state behavior in a finite state machine can be represented more clearly by using the state pattern.
In game development, the state pattern can be used to implement finite state machines to manage state transitions and behavior of objects.


7. Mediator mode (Mediator)

The intermediary mode is used to reduce the coupling between multiple objects, and concentrate the interaction between objects into one "intermediary object" for processing. (interaction hub between multiple subsystems)

scenes to be used illustrate
Interaction between subsystems Can be used as an interaction hub between subsystems in the game
UI system The intermediary mode can be used to extract the complex UI interaction relationship from each UI element and concentrate it in one intermediary object for processing
interaction between characters Interaction logic such as dialogs and transactions between roles can be separated from role objects, and intermediary objects can be introduced for processing
event system Concentrate the processing logic of events such as players being defeated and items being collected into an intermediary object to simplify the process of publishing and subscribing events (observer mode is recommended)

8. Strategy

The Strategy pattern allows dynamically changing the behavior of an object at runtime. By using the Strategy pattern, you can encapsulate a set of interchangeable algorithms into a set of independent classes, simplifying your code and improving maintainability and extensibility.

scenes to be used illustrate
Calculation of character attributes You can use the strategy pattern to separate different attributes and calculation methods for easy modification and use
level generation Different level generation algorithms can be encapsulated as a set of independent classes, and the level generation strategy can be dynamically switched as needed at runtime
Game Difficulty Adjustment ditto

Strategy Pattern vs. State Pattern

"State is to switch among a group of states, and there is a corresponding and connected relationship between states; Strategy is composed of a group of classes that have no relationship, and do not know the existence of each other. State is limited by the switching rules of the state machine, in the
design All possible states will be defined in the early stage, even if they are added later, they need to be related to the existing states, instead of adding them if they want; Strategy is a design pattern formed by encapsulating computing algorithms, and there is no any relationship between algorithms. Dependency, new algorithms can be added or replaced immediately."
—— "Design Patterns and Perfect Game Development"


9. Template Method

The template method pattern defines the skeleton of an algorithm in a method and abstracts some repetitive steps from subclasses to superclasses. In this way, template methods allow subclasses to redefine certain steps of an algorithm without changing the structure of the algorithm. (General process)

scenes to be used illustrate
Level loading The basic structure of level loading (such as preloading resources, initializing scenes, loading characters, etc.) can be defined in an abstract base class, and the specific loading steps can be delayed to subclasses
achievement system You can use the template method pattern to define an abstract achievement class, which contains basic achievement checking skeleton methods, and implements specific achievement checking logic in subclasses
Online game login The login process is fixed through the template method mode, such as displaying the login screen, selecting the login method, entering the account password, sending a request to the server, etc., so that the login function subclass can realize specific operations

10. Command mode (Command)

命令模式将请求封装为对象,将客户端的不同请求参数化,并配合队列、记录、复原等方式来执行请求操作。

使用场景 说明
交互逻辑 在MVC框架中,可以用于分担 Controller 层的交互逻辑,让很多混乱的交互逻辑代码从 Controller 迁移到 Command 中
操作记录 通过存储已执行的命令对象,可以轻松实现撤销和重做功能(如移动单位、放置建筑等)。可用于实时策略游戏和编辑器等场景
事件系统 可以将一系列事件通过命令模式封装起来,使其可以更灵活的调用

在凉鞋老师的框架中:

  • 事件由 系统层 向 表现层 发送
  • 表现层 只能用 Command 改变底层系统层的状态(数据)
  • 表现层 可以直接查询数据

11. 责任链模式(Chain of Responsibility)

责任链模式为请求创建了一个接收者对象链。这些接收者对象按顺序处理请求,直到其中一个处理了该请求为止。

使用场景 说明
关卡切换 可以设置各关卡切换条件,当条件达成时跳转到对应关卡。在通关判断上,可以配合策略模式,让通关规则具有其他形式变化
AI决策 将不同的AI行为链接在一起,让AI根据当前情况处理决策请求,从而实现灵活的AI行为控制

12. 观察者模式(Observer)

观察者模式定义了一种一对多的依赖关系,当一个对象(主题)的状态发生变化时,所有依赖于它的对象(观察者)都将得到通知并自动更新。

使用场景 说明
事件系统 可以实现一个全局的游戏事件系统,当某个事件触发时,所有订阅了该事件的对象都会收到通知并作出相应处理
成就系统 监测游戏中的各种事件(如角色升级、任务完成、特定敌人击败等),当满足成就条件时,自动解锁相应的成就并通知玩家

观察者模式 与 中介者模式

两者结构相同,但使用场景不同。
观察者模式可以理解为了使业务逻辑更加清晰,从中介者模式中分离出一种专门处理事件订阅与分发的设计模式(笔者的粗浅理解)。


13. 备忘录模式(Memento)

备忘录模式在不破坏对象封装的前提下,捕获对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

使用场景 说明
游戏存档 可以利用备忘录模式保存玩家的角色状态、关卡进度、游戏设置等信息
状态回滚 在角色受到负面效果或需要恢复到之前状态时,可以使用备忘录模式回滚角色属性
撤销操作 在游戏编辑器或游戏中的一些可撤销操作,可以通过备忘录模式记录并恢复对象的状态

14. 访问者模式(Visitor)

访问者模式可以定义一个能够在一个对象结构中对于所有元素执行的操作。访问者可以让你定义一个新的操作,而不必要更改到被操作元素的类接口。被访问者需要开放足够的操作方法和信息。

使用场景 说明
统计数据 在对游戏中的各种对象(如角色、敌人、道具等)进行统计时,可以使用访问者模式来实现,避免修改原有类定义
辅助管理类 当需要对各种对象(如角色、敌人、道具等)的“管理容器”类添加功能时,可以通过访问者模式减少对原有代码的更改

15. 迭代器模式(Iterator)

在不知道集合内部细节的情况下,提供一个按序方法存取一个对象集合体的每一个单元。(遍历)

使用场景 说明
遍历对象 循环语句(如 for 循环)就可以实现迭代器模式

16. 解释器模式(Interpreter)

定义一个程序设计语言所需要的语句,并提供解释来解析(执行)该语言。(翻译)

使用场景 说明
表达式计算 可以使用解释器模式来解析和计算游戏中的各种表达式

结构型 设计模式

17. 外观模式(Facade)

在游戏开发中,外观模式常被用于简化复杂系统的交互。通过为多个子系统提供一个统一的接口,将复杂的内部逻辑抽象为简单的调用。(高级封装)

使用场景 说明
音频管理器 创建一个音频管理器类,可以简化音频播放、暂停、停止等操作的调用。只需通过音频管理器接口来控制音频播放,无需关注音频资源的加载和播放器的创建
UI管理器 将UI系统中的交互逻辑,如按钮点击事件、文本显示等操作,封装在一个UI管理器类中,简化UI组件的访问和修改,同时降低UI系统与其他系统之间的耦合度
数据持久化 创建一个保存管理器类,可以简化保存和加载过程,同时方便后期扩展更多的存储功能

18. 桥接模式(Bridge)

桥接模式用于将抽象与实现分离,使它们可以独立地变化。使抽象类作为不同实现类间的桥梁。

使用场景 说明
角色与装备 可以将角色、装备的抽象与具体实现分离,使不同种类的角色可以搭配和使用不同种类的装备
输入系统 可以将输入设备(如键盘、鼠标、游戏手柄等)的抽象与具体实现分离,从而简化输入设备的管理和扩展,同时保持游戏逻辑的独立性
游戏资源管理 游戏资源(如纹理、模型、声音等)可能需要支持多种格式和来源(如本地文件、网络下载、内存中的数据等)。可以将资源的抽象与具体实现分离
网络系统 可以将网络协议(如TCP、UDP、Websockets等)的抽象与具体实现分离,从而简化网络协议的管理和扩展

19. 享元模式(Flyweight)

享元模式的主要目标是通过共享相同的对象,来减少内存占用和提高性能。

使用场景 说明
游戏对象属性共享 将游戏中大量具有相同属性的游戏物体中的相同部分提取出来,进行统一管理

20. 组合模式(Composite)

组合模式将对象组合成树形结构以表示层次结构。组合模式使得客户端可以以一致的方式处理单个对象和对象组合。

使用场景 说明
UI层次结构 通过使用组合模式,可以轻松地组织和管理树型UI菜单,实现事件传递和布局调整等功能
游戏任务逻辑 可以将任务、子任务和条件等逻辑元素组织成树形结构,实现逻辑的判断和执行等功能

21. 装饰模式(Decorator)

装饰模式允许在不改变原始对象结构的情况下,动态地向对象添加新功能,从而实现功能的组合和扩展。

使用场景 说明
角色属性修改 可以通过装饰模式增加角色的属性(如生命值、攻击力、防御力等)
游戏界面扩展 可以游戏界面添加额外的功能(如特效、动画、音效等),这样实现起来比较灵活,修改也方便
数据加密解密 -

装饰模式已有目标增加功能非常方便,但是要避免盲目使用导致系统过于混乱,应将可能需要的功能列在早期的开发计划中。


22. 适配器模式(Adapter)

适配器模式将一个类的接口转换成另一个类所期望的接口,使得原本接口不兼容的类可以一起工作,提高组件的复用性和扩展性。(转接口)

使用场景 说明
第三方库集成 当需要集成不同的第三方库(如广告、支付、社交等)时,可以使用适配器模式统一接口,方便切换和扩展不同的第三方库
输入设备兼容 可以统一不同输入设备(如键盘、鼠标、手柄等)的接口,实现多种输入设备的兼容和扩展
游戏引擎升级 当游戏引擎升级后,一些接口可能发生变化,使用适配器模式可以降低升级带来的影响
网络通信协议适配 在多人在线游戏中,可能需要支持多种网络通信协议(如TCP、UDP、WebSocket等),可以使用适配器模式统一接口,方便扩展和切换不同的通信协议

23. 代理模式(Proxy)

代理模式为其他对象提供一种代理以控制对这个对象的访问。代理模式可以用于延迟加载、安全控制、日志记录等功能。

使用场景 说明
优化测试 可以使用代理模式测试游戏优化的效果,以免去修改原始类的接口及实现
网络代理 在多人在线游戏中,可以使用代理模式处理与服务器的通信,方便进行数据加密、压缩、缓存等操作

在学习设计模式的过程中,我发现设计模式其实是面向对象的数据结构。
一个由0和1组成的系统,通过各种各样的数据结构和算法,层层编织出能够模拟现实的游戏世界,这实在是太美妙了!

Guess you like

Origin blog.csdn.net/Dugege007/article/details/130331557