Skip to content

[bug] maxFPS 不生效:模型仍按屏幕刷新率渲染(Ticker.shared 与 app.ticker 不是同一个) #1041

Description

@345-yu

描述 Bug

设置里的「最大帧率」(maxFPS)无法限制实际渲染帧率。设为 60 后,Live2D 模型仍然按显示器刷新率渲染 —— 我的屏幕是 240Hz,实测模型就是稳定跑在 240 fps,每秒约 39,600 次 WebGL 绘制调用。

在高刷屏上这意味着 GPU 负载是预期值的 4 倍,玩游戏时桌宠会跟游戏抢 GPU 提交队列。

重现步骤

  1. 偏好设置 → 猫咪 → 最大帧率 设为 60,重启 BongoCat,确认 cat.json 里确实是 "maxFPS": 60

  2. 给 WebView2 开远程调试(因为 bongo-cat.exe 被设为管理员运行,WebView2 Runtime ≥150 只认 HKLM 策略):

    HKLM\Software\Policies\Microsoft\Edge\WebView2\AdditionalBrowserArguments
      bongo-cat.exe = --remote-debugging-port=9222
    
  3. 通过 CDP 连到桌宠页面 http://tauri.localhost/index.html/#/,给 WebGLRenderingContext.prototype.drawElements / drawArrays 打计数补丁

  4. 统计「绘制批次」:每渲染一帧会连续发一串 draw call,批与批之间必有 >2ms 空隙(等下一次 rAF),批数即真实渲染帧率

实测数据

maxFPS 设为 60,连续 8 秒每秒采样一次,数值几乎没有抖动:

指标 实测值
真实渲染帧率(绘制批次/秒) 240.0
requestAnimationFrame 频率 240.0(= 屏幕刷新率)
每次渲染的绘制调用数 165
每秒绘制调用数 约 39,600
画布尺寸 420×420 后备缓冲(CSS 280×280,dpr 1.5)
BongoCat 占 GPU 3D 引擎 2.44%(空闲桌面,RTX 4060 Laptop)

把 maxFPS 设为 60 / 120 都是同样的结果,渲染帧率始终等于刷新率。

预期行为

maxFPS 设为 60 时,模型的渲染帧率应为 60,绘制调用数相应降到约 1/4。

原因分析

问题出在 Ticker.shared 和 app.ticker 不是同一个 Ticker。

src/utils/live2d.ts:

// L29-L37:创建 Application 时没有传 sharedTicker
this.app = new Application()
return this.app.init({
  view,
  resizeTo: window,
  backgroundAlpha: 0,
  autoDensity: true,
  resolution: devicePixelRatio,
})

// L67:Live2DSprite 用的是共享 Ticker
this.model = new Live2DSprite({ modelSetting, ticker: Ticker.shared })

// L133-L135:但限速只设了共享 Ticker
public setMaxFPS(fps: number) {
  Ticker.shared.maxFPS = fps
}

PixiJS v8 的 ApplicationOptions.sharedTicker 默认值是 false,也就是 Application 会新建一个自己的 Ticker 来驱动渲染循环,而不是用 Ticker.shared。

所以 Ticker.shared.maxFPS = fps 只能限制挂在共享 Ticker 上的回调(Live2DSprite 的 update),渲染循环跑在 app.ticker 上,完全不受限制,于是一直按 rAF 的节奏(= 屏幕刷新率)重绘。

建议修复

任选其一:

// 方案 1:让 Application 直接用共享 Ticker
return this.app.init({
  view,
  resizeTo: window,
  backgroundAlpha: 0,
  autoDensity: true,
  resolution: devicePixelRatio,
  sharedTicker: true,
})
// 方案 2:限速时两个 Ticker 都设
public setMaxFPS(fps: number) {
  Ticker.shared.maxFPS = fps
  if (this.app) this.app.ticker.maxFPS = fps
}

软件信息

{
  "appName": "BongoCat",
  "appVersion": "1.1.0",
  "platform": "windows",
  "platformArch": "x86_64",
  "platformVersion": "10.0.26200",
  "webview2Runtime": "153.0.4234.48",
  "display": "2560x1600 @ 240Hz, HDR on",
  "gpu": "NVIDIA GeForce RTX 4060 Laptop GPU"
}

对应源码为 master 分支当前状态(44f44bc,2026-04-28)。

附加信息

相关 issue:

刷新率越高的屏幕受影响越大:60Hz 屏上限速 60 看不出问题,240Hz 屏上实际负载就是设定值的 4 倍。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions