【游戏编程扯淡精粹】游戏编程设计模式
【游戏编程扯淡精粹】游戏编程设计模式
文章目录
本文最初写于2018/9/4
毛星云 RIP
如何练习设计模式
- 基本盘:长期维护一个大型工程,持续积累
- 维护一个设计模式表格,日常查找使用
- 多学几门编程语言和编程范式,看不同的语言如何更好地解决问题
- 开发DSL和框架/架构在高纬度解决问题,直接干掉设计模式,减少业务逻辑层的代码量
所以我们只能通过复杂的程序来学习设计模式。
你不管看别人的程序也好,自己写程序练习也好,那必须要复杂,复杂到你不用设计模式就做不下去,这才能起到学习设计模式的作用。
维护一个表格
- 设计模式名称
- 适用情形/案例
- 代码示例
- 详细描述
实际使用的时候,是从当前情景匹配适用情形去找到适合的设计模式
资源链接
【游戏设计模式】之四 《游戏编程模式》全书内容提炼总结 - 知乎
miloyip/graphvizuml: 使用 Graphviz 绘画 UML 图
并发设计模式
Active object - Wikipedia
Balking pattern - Wikipedia
Guarded suspension - Wikipedia
Reactor pattern - Wikipedia
编程语言和设计模式
Design Patterns in Dynamic Languages // Python
Channel (programming) - Wikipedia // GO
Hygienic macro - Wikipedia // Scheme
UML
UML方案
我选择的三种UML方案:
- Graphviz
- draw.io
- Microsoft Viso
Graphviz的方案比较轻量,适合程序员,可以用Git进行版本管理,但是有学习门槛
常见UML
- 类图
- 顺序图
- 状态图
- 活动图
UML | 适用情景 |
---|---|
类图 | 类OOP设计 |
顺序图 | 时序,前后端交互 |
状态图 | 状态机 |
活动图 | 多线程fork/join流程 |
我个人最常用的是顺序图和状态图,比源码和文字描述的表现力更强
经典设计模式
经典设计模式主要适用于C++,C#语言的OOP编程范式
设计模式的目标
目标是得到高扩展性的代码
在应对频繁需求变更和迭代的过程中能够:
- 快速实现新需求
- 容易理解,容易调试
- 扩展代码,而不是修改代码
设计模式的原则
- 面向接口
- 接口细粒度,调用功能是面向接口的
- 单一职责
- 避免继承一个类
组件模式/桥接模式
参考:
- Unity的MonoBehaviour和Component
- Ogre的OgreRoot和Plugin
适配器模式
这个模式直接对应生活中的转接口
比如我去英国旅游,但是国内外的电源接口是不一样的,这时就需要一个电源接口适配器,将国内接口转换成英国接口
编程的适配器模式也是一样的,但是适用情形也是两头的代码已经都别人写好了,我来对接时,写一个适配器进行转接
命令模式/解释器模式
参考:
- Lua的vmloop
- Unity的Coroutine机制
可以将Coroutine机制封装一下,把一个命令包装成一个Coroutine,再把Coroutine串联在一起
工厂模式
主要是因为ctor是特殊函数,不支持虚函数
所以包装成工厂函数,就可以使用一般的多态机制,更加灵活
class Factory {
public:
Product* createProduct(productType type) {
switch (type) {
case TypeA:
return new ProductA();
case TypeB:
return new ProductB();
case TypeC:
return new ProductC();
default:
return nullptr;
}
}
};
代理模式
代理(Proxy)这个词在具体领域,比如网络,可能有非常多的概念
生活中的中介可以看作代理,中介会帮你完成你本身完成不了的工作
你只需要与中介对接,向中介提出请求,中介去执行,并将结果返回给你,你不需要知道中介是怎么做的
编程中,可以看作是Client-Server模型,Proxy Server做了一个抽象隔离,让Client使用简单的接口完成复杂的任务
原型模式
案例:
- RPG游戏的怪物类型机制
本质是数据驱动地去构造一个类型
一般的RPG需要制作大量的换皮怪来应对玩家的等级和装备成长
可以通过功能模块的组合来拼装出一个新的怪物类型,不需要编写代码
装饰器模式
参考:
- Python的装饰器
单例模式
参考:
- Ogre的OgreSingleton
责任链模式
一种fallback处理机制
案例:
- 查找路径,比如lua require查找模块机制
- 游戏事件处理责任链,遍历事件处理器,直到事件被处理
组合模式
案例:
- 文件系统的文件树
文件和目录都继承自节点
删除文件就是删除节点,删除目录是删除子树
外观模式
就是包装类
比如游戏引擎对图形接口和物理引擎都会重新包装一遍,因为原始的接口集合太复杂太难用了
享元模式
案例:对象缓存或者对象池
就是复用内存和对象
策略模式
从多个alternative中选择一个
迭代器模式
C++/C#自带,这已经不是设计模式了
游戏设计模式
沙箱模式
原始的沙箱模式没有实践意义
沙箱这个概念需要了解:
- 脚本执行网络代码需要沙箱隔离,参考Lua沙箱
- 引擎开发过程中,分离出引擎层,提供一个沙箱环境用来编写Demo
这个沙箱机制ZeloEngine已经实现,Demo全部在Lua脚本沙箱中编写运行,可以动态切换,开发Demo不会导致频繁编译引擎
【ZeloEngine】沙箱机制_游戏编程扯淡精粹-CSDN博客
脏标记模式
案例分析:
- UI脏矩形优化
- UI界面View没有更新,就不需要重新计算View
- transform树更新计算脏标记优化
- transform节点更新只影响节点的子树,不影响其他节点不需要更新
transform树的脏标记更新ZeloEngine已经实现
需要框架,内容太多,建议单独查
事件队列
参考:
- 饥荒的StateGraph和EntityScript
其他设计模式
控制反转 & 依赖注入
MVVM
参考:
- WPF
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!