尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Cocos Creator 屏幕震动实战:4 种实现的每帧开销、参数取值与选型表

Cocos Creator 屏幕震动实战:4 种实现的每帧开销、参数取值与选型表 Cocos Creator 屏幕震动实战4 种实现的每帧开销、参数取值与选型表【免费下载链接】cocos-engineCocos simplifies game creation and distribution with Cocos Creator, a free, open-source, cross-platform game engine. Empowering millions of developers to create high-performance, engaging 2D/3D games and instant web entertainment.项目地址: https://gitcode.com/GitHub_Trending/co/cocos-engineCocos Creator 3.x 没有内建的屏幕震动组件相机位移与衰减需要自己实现且不同写法的每帧成本差一个数量级。本文以移动相机节点并逐帧衰减为核心实现给出 4 种方案的每帧运算与堆分配数据、完整参数取值范围以及一段可直接挂载运行的最小组件。读完可以直接在项目里完成选型与接入。先把问题复现出来每帧随机位移的相机抖动可复现场景一个 3D 项目受击时给 Camera 节点加每帧 ±20 设计像素的随机偏移持续 0.3 秒后手动停止。实际现象有三点帧间偏移跳变可达 40 像素理论上界为 2 倍振幅肉眼看到的是雪花屏式白噪声而不是围绕中心晃的震动偏移量本身不衰减0.3 秒一到直接归零结束得同样生硬在 120Hz 设备上抖动频率恰好翻倍观感不一致。根因是一句话每帧偏移与上一帧无关轨迹没有连续性也没有能量衰减模型。后面所有改进都围绕这两点展开。数据先行4 种屏幕震动方案的每帧开销对比先亮结论短时打击反馈用前三种即可单帧微秒级、零堆分配差别只在衰减曲线形状长时 rumble 才考虑噪声方案因为它每帧产生真实垃圾对象。方案每帧核心运算每帧堆分配单帧耗时量级适用边界每帧随机2 次Math.random 1 次setPosition0~1 μs时长 0.2s 的即时反馈lerp 衰减随机2 次随机 1 次exp 2 次 lerp0~1 μs通用打击、UI 反馈阻尼振子弹簧2 轴欧拉积分4 乘 4 加0~1–2 μs爆炸、重击要自然衰减包络ParticleNoise 噪声每帧 2 次noise()每次含 256 轮循环512 次写入、8 次角点渐变、6 次 fade、7 次插值2 个 512 长度局部数组约 8KB~10–30 μs另有 GC 压力长时低幅 rumble、有机感耗时量级按桌面 V8 环境从运算次数推算不是固定基准每帧堆分配一列是实打实的代码行为——引擎自带噪声类ParticleNoise源码在cocos/particle/noise.ts每次调用都会新建一个 512 长度的局部数组60fps 下即约 480KB/s 的垃圾产生速率这是它只适合低频场景的直接原因。从朴素版到定稿版屏幕震动实现的三步演进第 1 步朴素版每帧随机。能跑通但帧间无连续性就是上面复现的雪花屏camNode.setPosition( baseX (Math.random() * 2 - 1) * intensity, baseY (Math.random() * 2 - 1) * intensity, baseZ);改的原因偏移要跟手不能每帧从零掷骰。第 2 步改进版能量衰减 位移平滑。振幅按指数律衰减单帧位移再向新目标 lerp 一次两个环节都写成exp(-k*dt)形式保证帧率无关。decay是能量衰减率1/s取 4~10越大停得越快smooth是位移平滑率1/s取 8~16越小毛刺感越强let amp 20, off 0; const decay 8, smooth 12; // 1/s update(dt: number) { amp * Math.exp(-decay * dt); off ((Math.random() * 2 - 1) * amp - off) * (1 - Math.exp(-smooth * dt)); camNode.setPosition(baseX off, baseY, baseZ); if (amp 0.001) { amp 0; off 0; } }改的原因指数衰减是渐近的结束时要手动写回基准位且打击类效果需要先大后小的物理包络而不是等幅抖动。第 3 步定稿版阻尼弹簧。对单次重击用弹簧振子的欧拉积分k是弹簧刚度越大回中越快、振荡越密c是阻尼系数越大衰减越快越小越弹impulse是受击瞬间施加的初速度px/s取 300~800let x 0, vx 0; const k 90, c 6; function hit(impulse: number) { vx -impulse; } update(dt: number) { const ax -k * x - c * vx; vx ax * dt; x vx * dt; camNode.setPosition(baseX x, baseY, baseZ); if (Math.abs(x) 0.01 Math.abs(vx) 0.01) { x 0; vx 0; } }长时 rumble 则回到第 2 步结构把Math.random()换成ParticleNoise的低频层时间系数 2~4叠加一个幅度占比 0.2~0.5 的高频层时间系数 16~32但务必按后文第 4 个坑处理它的分配问题。选型决策表场景到关键参数取值范围场景方案关键参数取值范围UI 点击、轻反馈lerp 衰减随机振幅 0.5~1.5 设计像素decay 6~10smooth 10~16命中、爆炸、重击阻尼振子k 40~120c 4~10冲量 300~800 px/s长时 rumble地震、巨物ParticleNoise 低频高频叠加低频时间系数 2~4高频 16~32高频幅度占比 0.2~0.5总振幅 4~12注意振幅单位统一用设计像素先除以view.getDesignResolutionSize()的宽换算再乘实际位移避免不同分辨率下强弱不一致。踩坑记录屏幕震动的 4 个高频问题与修复坑 1现象120Hz 设备上震动时长约一半抖动快一倍。原因逐帧固定倍率衰减如每帧 ×0.9与帧率绑定0.9^60 与 0.9^120 不等价。修复所有衰减改写为Math.exp(-k * dt)k 以 1/s 为单位。坑 2现象震动结束后相机停留在基准位偏移 1~2 像素处UI 对不齐。原因指数衰减渐近于 0位置永远精确不到基准点。修复振幅低于阈值0.01时强制写回基准位并清零状态上面三段代码均已包含该分支。坑 3现象3D 相机震动的同时 2D UI 跟着晃或反过来。原因震动加在 Canvas 或共享相机上2D/3D 共用了同一份视口变换。修复3D 震动只改 Camera 节点位置UI 反馈单独抖 Canvas 节点两者不同时驱动。坑 4现象长时 rumble 期间帧耗时呈锯齿状GC 日志持续增长。原因ParticleNoise.noise()每次调用分配一个 512 长度局部数组见cocos/particle/noise.ts每帧调 2 次。修复预生成 1~2 秒固定长度的噪声序列循环采样或将噪声调用降频到 30Hz 再对结果插值。时间来源顺带一提组件update(dt)的dt由引擎传入秒制源自cocos/game/game.ts的deltaTime直接用它即可director.getDeltaTime()自 3.3.0 起已标记弃用不要走它。30 分钟跑通最小实现用 Cocos Creator 3.x 新建一个 3D 项目把下面组件挂到 Camera 节点默认amplitude20、decay8在受击或按钮点击回调里调用trigger()预览验证衰减包络decay为 8 时0.1s 剩约 45% 振幅0.15s 剩约 30%exp(-8t)0.5s 后归零。import { ccclass, property, Component, Vec3 } from cc; ccclass(ShakeCam) export class ShakeCam extends Component { property amplitude 20; property decay 8; private base new Vec3(); private amp 0; trigger() { if (!this.amp) this.base.copyFrom(this.node.position); this.amp this.amplitude; } update(dt: number) { if (!this.amp) return; this.amp * Math.exp(-this.decay * dt); this.node.setPosition(this.base.x (Math.random() * 2 - 1) * this.amp, this.base.y, this.base.z); if (this.amp 0.001) { this.amp 0; this.node.position this.base; } } }边界与延伸2.5D 相机可把 Z 轴位移锁死为常数只保留 X/Y 两轴得到平面震动。需要与后期效果联动命中定帧、全屏震屏 shader时改由每帧偏移量驱动材质 uniform代价是一次额外的全屏 pass。多震动源同时触发时先合成振幅再统一衰减避免多路独立衰减互相抵消。分别在 60fps 与 120fps 预览下验证震动总时长一致帧率无关性确认结束时有阈值写回基准位的分支生效无残留偏移核对振幅参数单位为设计像素更换分辨率策略后复测若启用噪声路径跑一轮 GC 日志确认分配频率在可接受范围【免费下载链接】cocos-engineCocos simplifies game creation and distribution with Cocos Creator, a free, open-source, cross-platform game engine. Empowering millions of developers to create high-performance, engaging 2D/3D games and instant web entertainment.项目地址: https://gitcode.com/GitHub_Trending/co/cocos-engine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表