LUACN论坛

 找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
热搜: YJWOW MagicStone BoL
查看: 263|回复: 7

BEE进阶研究第四季--协程的原理简单认识

[复制链接]
发表于 2024-8-10 12:13:17 | 显示全部楼层 |阅读模式
本帖最后由 vshrd 于 2024-8-17 07:25 PM 编辑

--对于萌新宝宝而言,请切实掌握了前三篇教程后再来看这篇教程
前言:        
        本篇确实冥思苦想了很久.不是协程本身很难,而是协程涉及到的知识点太多.我需要精简提炼把只需要了解不需要深究的其他知识点给想办法以萌新宝宝也能听懂的方式给描述出来.
        可能经过九年义务教育,大家对知识有误解,觉着知识分布是线性的,即上完一年级的学,就可以开始学习二年级的知识,以此类推.但其实知识是图形结构,即A领域需要部分B领域的知识作为铺垫.人的精力有限没办法完整的把B领域的知识完整学一遍,所以就需要有即懂A又懂B的人来进行归纳总结,把B领域里涉及到A领域的知识提炼出来,降低本来是学习A方向的人的学习门槛和学习成本.而这也就是本篇教程需要做的事情了.
         之后我会从框架结构,帧,同步异步,多线程几个方面简单介绍,最后再到协程.不过各位不用担心知识过于复杂,因为协程之前的所有知识都只需要了解,同时我也只会以极简极易懂的方式进行进行描述.各位同学可以放心吧前面的铺垫内容当作趣味小科普趣味小故事来看待,即使没有理解也没有关系,等到后文还是正式涉及到相关部分的知识时再回头来看都行.我尽量以多讲故事少讲晦涩内容为思路.
          在这之后下一篇的教程就会从协程的原理简单认识进阶到协程的简单应用.然后再下一篇帖子我会给出一个面向对象的完整脚本进行解析,同时也是对前面所有知识点的一个回顾总结,然后本系列教程就全部结束.希望各位能真正把这些东西啃明白的同学能踊跃发帖交一下作业,把学习区只会出现打地鼠脚本的这个模式给破除掉.
         另外如果对教程里有什么地方没太看明白,或者是忽然涉及到了一个知识盲区但我没有细讲的,都可以留言提问.我会尽力解答.

         以上,祝各位真心想玩儿好这个东西的同学能真的学到东西~!武运昌隆





一.框架
框架其实就类似与主机上的主板承载着各种硬件一样,框架承载着各种模块和逻辑支撑着一个程序的运行.
当我们不考虑细节,把一个程序的框架抛去所有杂七杂八的东西,极简化之后,就能得到这样一个东西

你可以理解为,魔兽等所有游戏都是这么去运行的.即使他在实际应用当中会非常复杂
远不止我画出来的这样简单.但我们只要认识到框架本质上就是干这事儿的即可.





二.帧
通过认识框架我们可以得知,程序的运行其实就是一个不停的在循环的一套逻辑
在我们发出退出的指令之前,他们会无限循环.
那么每循环一次,屏幕上的画面就会刷新一次
而这,就叫一帧.

这个肯定大部分了解过显示器的人都知道,不算什么特别难的知识.
那么一个趣味小问答:
一个稳定60帧的画面     和一个最低90帧,最高120帧的画面
哪一个会更流畅呢?

可能大部分人选择后者,因为后者的最低帧率也比前者高出了1/2;
但其实答案是反直觉的.
人的眼睛普通人能识别到21帧,超级人能识别到27帧
双方都远远高出了这个值.但是受到视觉暂留的影响,有波动的帧率会比稳定的帧率更卡.


所以对于开发者而言,帧率的稳定性远比帧率的上限更重要.
所以就诞生出了锁帧.
回顾到前面所提到的框架,也就是说我们不需要程序自行无脑循环,而要去控制框架的循环频率.

那么问题又来了,锁帧大家都知道了,但是具体锁多少呢?
在早期硬件条件比较差时,开发者一琢磨,人类的视觉极限也就27帧了,那就锁个30帧完事儿了呗.
锁30帧,也就是一秒钟框架需要循环30次,合计每帧需要33毫秒.
如果这一帧的逻辑不到33毫秒,那也得给我等够了33毫秒才能进行下一次循环.
如果你这一帧的逻辑超过了33毫秒,这会导致游戏刷新延后,
也就是我们俗称的"掉帧".那对不起,你得去给我做优化,节约开销,
优化不下来那就砍功能,总之为了满足用户体验,我们必须至少得达到锁帧的频率;

而后来,随着硬件的疯狂迭代,厂商发现我即使在资源压力最大时,也能满足七八十帧.
那就从30帧进化到60帧呗.

看到这里可能有同学会好奇,为什么某些游戏,比如CS,他就不锁帧?
原因有很多,各方各面的,我挑几个重点讲讲.
第一,FPS是在游戏方向开发难度最低的游戏,换句话说就是逻辑最少的游戏.
算力压力?不存在的,不过是几个模型的移动旋转,开枪就生成子弹,碰撞检测,扣血,就完事儿了.
能有啥算力压力?(当然这里指的是游戏本身的逻辑,我们耳熟能详的显卡杀手游戏,或者所泰坦陨落这样的,他们的压力是渲染,而不是游戏逻辑本身)

第二.公平.
假设两个玩家一个60帧,一个120帧.
双方同时朝对方头部开枪,而开枪的瞬间处于帧结算的下一个瞬间.
那么框架响应到你的鼠标左键按下并生成子弹并像服务器发送请求所需要的时间一个是16毫秒,一个是8毫秒
毫无疑问,先像服务器发送请求的玩家活下来了,别说8毫秒了,你就是早1毫秒也是你赢.
所以看似在追求公平,其实反而不公平,竞技本身除了技术,同时也是硬件和网速的比拼.

那么趣味小科普就到这里.接下来讲同步异步.





三.同步异步,单线程多线程

通过前文的了解,我们知道了程序被锁帧后会按固定的频率来进行循环,
当程序实际占用低于这个频率,说明没有将性能充分利用
(对于玩家来说,玩游戏时帧率上限越高,代表自己计算机性能越好从而产生优越.
但其实对于开发来说,这其实是负面评价.说明开发没有去压榨性能.)
当程序实际占用高于这个频率,则需要进行效率优化来防止掉帧

那么有没有一种可能,我的程序中就是有那么一部分的数据计算极其复杂,
远高于锁帧所限制的时间呢?
比如一帧本来只给了我16毫秒,但是我的数据计算实际占用了10016毫秒.
如果碰到了这种情况,就会出现我们常见的,程序卡死,未响应.
直到10秒后才恢复正常.

为了解决这个问题,就诞生了多线程
我还是画个图举例子

那么到了这里就皆大欢喜了.只要我的机能足够高
理论上再复杂的数据处理也不会导致我的帧结算时间延后.
嗯,概念就理解到这里就行了.
而这就叫异步.
换句话说,前文的那个图,就是只有一条线下来的那个就叫同步.
同步过程中某个任务阶段被阻塞,即会导致整个程序进程阻塞.
而异步可以将复杂数据处理放到其他线程中进行
而框架始终可以在任何情况下都保持正常的运行效率.





四.协程
通过前文的了解,我们了解到了多线程对比单线程的优势.
听上去多线程完爆单线程.
但实际上真正能运用多线程的环境很少,至少你在公司的技术地位到达一定高度前很少.
一方面游戏开发其实想要完全压榨性能也没那么容易,所以没什么多线程出场的机会.
另一方面多线程本身是个很难很深的东西.对于新手来说,就像递归一样,是个很不安全不稳定的炸弹.
没用好的话极易造成游戏崩溃

可能对于很多高级语言来说,多线程不就是Thread.Init(),然后给他分配任务就完事儿了么.
但这主要得利与前人大佬的封装,如果本身能完全把多线程啃明白的话
那就已经属于人上人的水平了,自然也不是本篇教程的适用人群.


所以大部分情况下,我们始终得用单线程来做实现.
但我们会碰到一种情况,我们可能会有一种需要异步的需求
这个需求并不是为了降低运算压力,而是有些情况下就是需要用到异步
或者说如果能够异步的话,能让我们当前的需求实现变得更方便更简单.


基于这一点,就有了程.
携程是一种伪多线程,就是看起来像是多线程,其实是单线程,但实现了单线程环境下的异步.
我继续画个图来解释




看起来好像跟多线程很像.
其实协程是在单线程环境里一个特定的生命周期位置开了一个特殊的栈
并且允许这个栈在出栈时记录退出前的代码执行位置
从而可以在下一帧到来时重新从该退出位置继续执行任务.






那么本篇教程就到此结束了.
基本上全是理解概念上的东西.
可能乍一看,会让很多同学觉得莫名其妙,我只是一个写魔兽脚本的.
你说的这些跟我有毛关系呢?

所以下一篇教程,我们就会从实际需求出发
来解释一下协程的具体应用场景.
对协程进行一些简单应用.

以上,诸君武运昌隆~!





相关链接:
面向对象基础
状态机
回调函数
协程简单认识(包括框架概念,帧概念.同步异步概念也在这里)
(伪)动态数据,静态数据
协程实战应用

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?加入我们

x
回复

使用道具 举报

发表于 2024-8-10 16:41:45 | 显示全部楼层
框架:框架是一种软件架构,它为开发应用程序提供了一套基础结构和工具。框架可以简化开发过程,因为它预先定义了应用程序的某些部分,允许开发者专注于实现特定的功能。

帧:在计算机图形学中,一帧是指在显示器上显示的单个图像。程序通过不断地循环更新来刷新屏幕上的图像,每次更新称为一帧。帧率(FPS)是每秒钟显示的帧数,影响用户对动画或游戏流畅度的感知。

帧率稳定性与流畅度:尽管人眼可能无法区分超过一定数量的帧率,但帧率的稳定性对于避免画面卡顿非常重要。不稳定的帧率可能导致视觉暂留效应,使画面看起来不连贯。

锁帧:锁帧是一种技术,它通过限制程序的循环频率来确保帧率的稳定性。例如,锁定在30FPS意味着每帧有大约33.33毫秒的处理时间。

硬件发展与帧率:随着硬件性能的提升,开发者可以提高游戏的帧率,从30FPS提升到60FPS,以提供更流畅的体验。

竞技游戏中的帧率问题:在某些竞技游戏中,如CS(反恐精英),不锁帧可能是为了保持公平性。因为不同玩家的硬件性能可能导致不同的响应时间,这可能影响游戏结果。

同步与异步:这是两种不同的编程模式。同步操作要求程序等待一个任务完成后才能继续执行下一个任务,而异步操作允许程序在等待一个任务完成的同时执行其他任务。

做一个梗概 方便后人检索
回复 支持 0 反对 1

使用道具 举报

发表于 2024-8-10 21:31:13 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2024-8-10 22:50:50 | 显示全部楼层
谢谢分享谢谢分享
回复 支持 反对

使用道具 举报

发表于 2024-8-18 16:34:05 | 显示全部楼层
是不是少放了两个图?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-8-18 16:46:54 | 显示全部楼层
xiaoyao1 发表于 2024-8-18 04:34 PM
是不是少放了两个图?

啥图?
回复 支持 反对

使用道具 举报

发表于 2024-8-18 17:21:57 | 显示全部楼层

奇了怪了,之前一直看不到后面两个图,你这一回复,这两图就出来了
回复 支持 反对

使用道具 举报

发表于 2025-11-17 15:39:00 | 显示全部楼层
我也看不到图,回复下试试
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

小黑屋|手机版|Archiver|LUACN论坛

GMT+8, 2026-5-31 06:17 AM , Processed in 0.031847 second(s), 29 queries , Gzip On, Redis On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表