下载 App

关于游戏《因果》为什么需要在屏幕刷新率为60hz的环境下运行

精华修改于2025/11/0789 浏览技术交流
在这里感谢《窗口旅行 Out Of Bounds》的作者发现了最大的问题,请大家多多支持《窗口旅行 Out Of Bounds》
如标题所示,这一篇帖子用于说明最大的恶性bug出现的原因
在完整说明之前需要知道开发《因果》时使用的技术和前置知识储备
在游戏引擎的普及下,大部分开发者会遗漏一个很致命且隐性的问题:游戏运行时的帧数
有一小部分pvp游戏,会出现“屏幕刷新率高,游戏运行的帧数越高”的问题,例如《Bodycam》
这看起来是一个好结果,但它实际达成的效果却是由设备优劣带来的不对等体验,尤其是基础体验
拿最基础的移动举例子,如果奉行“屏幕刷新率高,游戏运行的帧数越高”就会出现以下结果:
“屏幕刷新率越高,相较于其他屏幕刷新率比你低的设备,你移动的越快”
为什么会出现这种情况?
在游戏开发时都会选择一个基础的动画更新函数来制作和判断角色当前的状态和信息
本质上来讲,动画更新函数就是一个定时器,在启动的时候就规定每隔一段时间就执行一次,直到这个定时器被移除(停止)
例如移动,先写一个函数,告诉编译环境“我需要将玩家移动到离当前位置距离为x,方向为v的位置”
然后将其放进动画函数里,动画函数就会按照规定的时间跨度一直持续执行“我需要……”这个函数
很多时候,由于开发者的疏漏或考虑不周,如果移动速度为x,他们会直接设定为“每一帧移动x这么远”
这是非常严重的错误
如果没有额外的锁帧技术,游戏每一帧将会以一个绝对的距离更新位置,但游戏运行的帧速不一定是绝对的
例如在一些高端设备游戏能够跑到90帧,意味着每一秒会执行移动90次,如果移动速度为10,那么在这个高端设备上一秒的移动距离为90*10=900
但在一些中低端设备只能跑60帧,这时一秒只会执行移动60次,在这个低端设备一秒的移动距离为60*10=600,一秒移动的距离直接少了接近一半
连最基础的移动都会受到如此大的影响,更不用说其他需要额外判定的功能和需要实际播放的动画
这下问题明了了,但如何解决?
我的答案是规定一个绝对的时间跨度(每隔16毫秒)更新一次动画,也就是一秒更新60次(1000/60≈16.6,这里取整为16毫秒)
请注意,这并不是说等到16毫秒后再执行一次动画更新函数,动画的执行和动画更新函数的执行是分开的
动画更新函数依旧按照原有的最高帧率执行,但在其中获取此次调用动画更新函数的时间戳,在判断到下一个时间戳之间的差大于等于16毫秒后就执行一次动画函数
具体例子为:
我有一个函数的名称为fun移动(),动画更新函数的名称为fun更新()
fun更新()执行的时候会获取一次时间戳,假设当前的时间戳为0
fun更新()第二次执行的时候又获取一次时间戳,假设当前的时间戳为8毫秒(模拟120帧的情况),此时时间差为8-0=8毫秒,不够16毫秒,所以继续执行fun更新()
fun更新()第三次执行的时候又获取一次时间戳,假设当前的时间戳为16毫秒,满足16-0=16毫秒的条件,此时执行一次fun移动(),恢复时间戳记录时间为0,继续进行从第一步的判断
这套方法的好处是对于一些帧动画有很强的适配性(例如2d格斗游戏中的动作序列帧),不会出现因为帧数高而导致快速鬼畜播放的效果
知道了帧数如何影响游戏体验后,再来谈谈《因果》中出现的“高于60hz就会卡死”的bug
我目前的所有游戏作品均由H5技术(html+css+javascript)开发,目的是为了进行多平台打包和分发,其中pc端使用nw.js来打包成exe文件,移动端使用cordova来打包成安装包
在js(javascript)中一般使用requestAnimationFrame()来更新动画,这个函数可以跑满设定的最高屏幕刷新率的效果来执行,且每次调用的时候都会返回一个名为currentTime的时间戳
方案和上文中提到的方案一样,但问题是我错误地将“恢复时间戳记录时间”这一行写到了函数末尾而不是“判断时间差大于16毫秒”里
TapTap
本来lastTime=null这一行应该写成lastTime=currentTime的
下面是较为完整的代码
TapTap
谨记不要熬夜写代码
我当时的思路应该是通过给lastTime赋值为null,再进行判断就会达到更新lastTime的目的
结果把lastTime=currentTime放到了函数的最后面
这就导致每执行一次动画更新函数都会恢复一次时间戳记录时间,在高刷屏上根本不会达成判断条件(即frametimeset>=16),预期中的下一帧根本不会到来,导致画面卡死(但仍然在运行)
解决方法很简单,将lastTime=null改成lastTime=currenTime,或将本存在于函数末尾的lastTime=currenTime移动到前面
问题是所有的动画控制方案都是这个模板,想全改是一项十分难绷的工程
另外还有一些有动态刷新率的设备,保不准真的会以一个很低的刷新率来运行
还是谨记不要熬夜写代码吧
还好在正式上线之前《窗口旅行 Out Of Bounds》的作者反映了游戏按下shift键就会卡死的现象,经过排查后确定是屏幕刷新率的问题,紧急处理后在开头新增了需要将刷新率调到60hz才能游玩的提示
在这里再次感谢《窗口旅行 Out Of Bounds》的作者,也希望大家多多支持《窗口旅行 Out Of Bounds》!
下面是《窗口旅行 Out Of Bounds》的地址,快去玩吧!
这里是《因果》的地址,卡关或有疑问的话建议在论坛查看攻略
猜你想搜
聚光灯游戏创作挑战 因果 刷新率60hz原因
不写代码不画图,1人21天用AI开发游戏截图
不写代码不画图,1人21天用AI开发游戏
👋 这是一篇用AI开发游戏的教程贴,以作者我本次参加聚光灯比赛为例~ 阅读完,你将收获: AI对游戏开发助力的点在哪? 如何丝滑地使用AI来进行游戏开发? AI在游戏开发中的局限在哪? 目录: 游戏创意 💡:还是得靠“人脑” 游戏方案 🗺️:人类种“种子”AI让它“发芽” 开发阶段 👨‍💻:让AI“小步快跑” 美术设计 🎨:搞定“风格一致性” 游戏音效 🎵:AI的“代码电子音” 总结反思 🤔:AI
精华
9 赞
2 回复
游戏开发中的项目资源管理截图
游戏开发中的项目资源管理
我是狂猎世界的开发者,大家感兴趣的可以看看我们本次聚光灯开发的项目。 在游戏开发的过程中,不管是个人项目还是集体项目,长期项目还是短期项目,往往都会遇到资源管理问题。这是创作者不得不面对的一个问题。 很多人可能觉得对于个人项目来说资源并不需要得到有效的管理,但事实是个人项目随着开发时间的增长也会出现爆炸式的资源数量膨胀,尤其是UI等琐碎物品的增加会大大的增加资源管理的难度。在这里我将会抛砖引玉,与
13 赞
3 回复
开源一Unity小框架,高效单例与模块化设计,减少样板代码截图
开源一Unity小框架,高效单例与模块化设计,减少样板代码
ProjectBaseUnity 是一个轻量的 Unity 小框架 介是我根据过往学习和上班拉磨中写的小框架, 在GJ和小游戏中使用过 核心是高效的单例与模块化设计,可以少写样板代码。 面板管理、事件总线、资源加载、对象池、音频和数据存储都开箱即用, 几十分钟就能把原型跑起来,适合小型项目和game jam 的快节奏开发。 易改易扩展[心动小镇_点赞],保持灵活度的同时也有规范可依,既能快速搭建也
精华
16 赞
2 回复
01:33
【聚光灯游戏推荐第三期】游戏荒?别划走!截图
【聚光灯游戏推荐第三期】游戏荒?别划走!
#发现好游戏 #平台跳跃 #猫 #人工智能 #推箱子 #反转 #发现好游戏 #聚光灯gamejam开发者日志 #聚光灯游戏开发心得接力
4 赞
有关《因果》的技术详解截图
有关《因果》的技术详解
#聚光灯游戏开发心得接力 在《因果》中我使用了一系列不常用的思路来制作游戏,希望我现在的思路在以后还是有帮助 首先想分享的是碰撞检测 一般来说,进行碰撞检测常用的方案是碰撞体,即检测玩家是否与障碍物进行碰撞 在我上一个游戏《T.B.I》中使用的就是这种技术 另外说明一下,我使用的是h5技术(html+css+javascript)来制作游戏,目的是为了实现跨平台打包和分发,在pc端使用nw.js
精华
5 赞
分享超级简单的ai生图方法,来自8号秘事制作经验截图
分享超级简单的ai生图方法,来自8号秘事制作经验
分享超级简单的ai生图方法。来自8号秘事制作经验 在上个月的8号秘事开发过程中,由于大家都是社畜,平时没有太多的时间,美术们在画完主场景后,没有太多时间去画一些交代剧情的美术资源。 我自己就通过搜索找到了一个非常简单的ai生图的方法,速度快效率高,而且不用花钱。虽然最终效果一般,但是综合来说,这还是个时间性价比很高的方法。 一.操作方法(附上神秘代码) 下面我来介绍使用方法,首先进入chatgpt
21 赞
1 回复
gamejam新手指南#3截图
gamejam新手指南#3
⭐本节目录 一、新手队伍会遇到哪些坑 二、策划案怎么写 三、团队友好协作小妙招 (——论11人野队如何实现0争执,0划水,0跑路) 《gamejam新手全指南》系列将在每晚18:00左右更新,会充分结合资料、参赛者介绍以及个人参赛体验,内容比较详细,[表情_开心]请大家请根据需要按标题查找~欢迎大家在评论区讨论及提问!! #gamejam #TapTap聚光灯独立游戏 #发现好游戏 #游戏制作 #
20 赞
有关《因果》的设计思路以及一些(目前)没有做进去的内容截图
有关《因果》的设计思路以及一些(目前)没有做进去的内容
#聚光灯游戏开发心得接力 好,是时候谈谈我是如何设计这个demo的了 通关的朋友可能在demo结尾听crisk讲了一点有关这个游戏的设计初衷,但碍于篇幅原因没能将细节完整展示,并且由于上线前对其中的机制进行了细微的调整,导致后续上传的版本与原先的设计有出入,所以她分享的设计和最终版本不太符合 一些通关的朋友也对游戏的机制有困惑,所以在这里将整个设计思路进行详细讲解 本篇更像长篇杂谈,属于梦到哪句
精华
3 赞
<赛博诊所>开发复盘:目标、规则与思路截图
<赛博诊所>开发复盘:目标、规则与思路
经过21天的鏖战,终于在倒数第二天把最终版本提交上去了。最后在平台上把游戏从头测了一遍,没遇到什么大问题,才终于松了一口气。 趁着记忆还热乎,想着复盘一下,记录这段经历,也分享一些我的思考。 我们做的是一款赛博朋克风格的点触类解谜游戏。基础设定是玩家扮演一位医生,通过线上连接潜入病人潜意识,治疗病人因植入体引发的赛博精神病。 从团队优势出发 我们团队有6个人,大多数成员身兼两职。我是美术出身,最近
精华
7 赞
2 回复
坐骑系统开发避坑指南:4阶分级+内丹养成,让玩家肝得心甘情愿截图
坐骑系统开发避坑指南:4阶分级+内丹养成,让玩家肝得心甘情愿
坐骑不仅是代步工具,更是玩家的“战力伙伴”。这次更新的坐骑系统(凡兽→灵兽→珍兽→仙兽),从设计到落地踩了不少坑,最终形成了“固定基础属性+随机资质+内丹升级”的闭环,分享给大家可直接复用的思路! 一、先踩坑:初期设计的3个致命问题 1. 只分阶不分属性,玩家觉得“换皮不换质”,最早坐骑种类少,获取毫无成就感; 2. 资质随机太极端,非酋玩家弃坑:初始版本资质区间跨度大,有的凡兽比灵兽还强
4 赞
1 回复