1. 项目概述当Unity WebGL遇上Firefox如果你和我一样是个Unity开发者并且已经不止一次地把项目打包成WebGL准备在浏览器里大展拳脚那你大概率也遇到过这个经典场景在Chrome、Edge上跑得好好的项目一换到Firefox火狐浏览器要么是加载半天没反应要么是直接黑屏甚至控制台还给你抛出一堆看不懂的错误。这感觉就像精心准备了一桌大餐结果客人用的餐具不对怎么也吃不到嘴里。“Unity打包的WebGL项目在火狐浏览器Firefox上打开”这不仅仅是一个操作步骤它背后是一整套关于浏览器兼容性、WebGL标准实现差异、Unity构建配置以及前端部署环境的综合课题。我经历过无数次在项目交付前被测试同学一句“Firefox上打不开”搞得焦头烂额。经过这些年的踩坑和填坑我总结了一套从原理到实操的完整应对方案。这篇文章我会带你彻底拆解这个问题从“为什么Firefox会出问题”开始一直讲到“如何确保你的WebGL项目在Firefox上丝滑运行”内容会非常干建议备好茶水。简单来说这个问题的核心在于Unity WebGL构建输出的是一套基于Emscripten工具链编译的JavaScript/WebAssembly代码它高度依赖于浏览器对WebGL、WebAssembly、JavaScript新特性以及特定HTTP头等标准的实现和支持程度。而Firefox作为一个在标准遵循上非常严格、同时在底层架构和性能优化上又有自己特点的浏览器与Unity WebGL运行时的一些“默认假设”或“优化路径”可能存在微妙的冲突。我们的目标就是消除这些冲突。2. 核心问题根源与Firefox特性解析在动手解决问题之前我们必须先搞清楚Firefox这位“客人”的脾气。盲目调整配置就像蒙着眼睛修车效率低下且容易引入新问题。2.1 WebGL标准支持与驱动黑名单首先是最基础的图形层。Unity WebGL渲染依赖于浏览器的WebGL实现。根据Unity官方手册Firefox 52及以上版本就支持WebGL 1.0Firefox 51及以上支持WebGL 2.0。看起来版本要求很低对吗但坑往往在这里。Firefox以及Chrome维护着一个GPU驱动黑名单。如果你的显卡驱动太旧、存在已知的稳定性或安全性问题浏览器会直接禁用或降级WebGL支持以防止崩溃或安全漏洞。在Firefox中你可以通过在地址栏输入about:support在“图形”部分查看“WebGL渲染器”和“WebGL 2渲染器”是否被启用。如果显示“已屏蔽”那问题根源很可能在此。注意很多开发者是在集成显卡或老旧独立显卡的笔记本上测试的这些设备极易触发驱动黑名单。尤其是在一些企业环境或公用电脑上显卡驱动常年不更新。为什么Firefox更敏感Firefox在图形稳定性和安全性上往往采取更保守的策略。一个在Chrome上可能只是轻微闪烁的驱动Bug在Firefox上可能导致整个标签页崩溃。因此它的黑名单可能更广泛。实操心得遇到黑屏或“WebGL context could not be created”错误第一步永远是检查about:support。如果是驱动问题更新显卡驱动是唯一正解。对于你无法控制用户环境的项目如面向公众的网页必须在游戏启动前做好能力检测并给出友好的提示而不是让用户面对一个空白页面。2.2 WebAssembly与内存模型差异从Unity 2018.1左右开始WebAssemblyWasm逐渐成为默认的发布格式取代了早期的asm.js。Wasm性能更好但不同浏览器对它的内存管理和即时编译JIT策略有所不同。Firefox的Wasm引擎基于Cranelift在处理超大内存初始请求或内存增长模式时可能与Unity运行时预期有差异。Unity WebGL构建时你会在Build Settings中设置“WebGL Memory Size”。这个值定义了Wasm线性内存的初始大小和最大值。如果这个值设置得过大比如超过2GB在Firefox中可能会在初始化阶段就遭遇失败。一个关键细节Unity的Wasm模块默认使用ALLOW_MEMORY_GROWTH选项允许内存按需增长。但在某些情况下Firefox对内存增长操作的性能开销或中断处理可能不如Chrome平滑这可能导致在加载大型AssetBundle或实例化大量对象时出现卡顿甚至中断。2.3 HTTP头与安全策略的严格性这是Firefox上独有的“大坑”之一也是很多“本地打开正常部署到服务器后Firefox不行”问题的根源。Firefox对某些HTTP安全响应头的要求极为严格。Cross-Origin-Opener-Policy(COOP) 和Cross-Origin-Embedder-Policy(COEP)为了启用像SharedArrayBuffer这样的高级特性这对Unity WebGL的多线程至关重要服务器必须返回正确的COOP/COEP头。如果配置不正确Firefox会直接阻止相关资源的加载导致脚本执行失败。Chrome虽然也要求但有时警告更宽松或者有回退机制。Content-Type头对于.wasm、.data、.js等文件服务器必须返回正确的MIME类型。例如.wasm文件必须是application/wasm。如果服务器尤其是某些简单的静态文件服务器或配置错误的后端返回了application/octet-stream甚至没有Content-TypeFirefox会拒绝执行而Chrome可能尝试推测并执行。HSTS (HTTP Strict Transport Security)如果你的网站使用了HTTPS并设置了HSTS但尝试通过HTTP访问Firefox会坚决阻止连接并显示“启用了被称为 HTTP 严格传输安全(HSTS)的安全策略Firefox 只能与其建立安全连接”的错误。你必须确保访问的URL协议http/https与服务器配置完全一致。2.4 IndexedDB与本地存储的兼容性Unity WebGL使用IndexedDB来模拟文件系统用于实现PlayerPrefs、Application.persistentDataPath以及AssetBundle的缓存。Unity官方手册明确指出Firefox 42及更早版本对于在iFrame中运行的内容不支持IndexedDB。这意味着什么如果你的WebGL内容被嵌入在一个iframe里这在很多网页游戏平台、广告嵌入或门户网站中非常常见并且用户使用的是旧版Firefox那么所有的本地存储功能都会失效。游戏无法保存设置也无法缓存资源每次访问都像第一次加载一样。虽然Firefox 43修复了此问题但你无法控制所有用户的浏览器版本。因此如果你的发布场景包含被iframe嵌入的可能这就成了一个必须考虑的兼容性问题。3. 构建配置优化针对Firefox的专项调整知道了问题在哪我们就可以在Unity构建阶段主动出击进行针对性配置从源头上减少兼容性风险。3.1 内存大小与初始化设置的权衡打开Project Settings - Player - WebGL Settings这里有几个关键设置WebGL Memory Size不要盲目设大。对于中度复杂的2D/3D项目256MB或512MB是一个安全的起点。你可以通过ProfilerWebGL目标分析实际内存使用峰值然后适当增加。对于Firefox建议初始值不要超过1GB1024MB除非你确信你的用户群体设备内存充足。Enable Exceptions建议设置为“None”或“Explicitly Thrown Exceptions”。将异常处理交给C#代码而不是让Emscripten处理所有C异常可以显著减少生成的Wasm/JS代码体积和初始化开销对所有浏览器都有益对Firefox的初始解析压力也有缓解。Code Optimization发布时务必选择“Release”模式并启用“Code Optimization”。这会让Emscripten进行最大程度的优化生成的代码更小、更快兼容性也通常更好。3.2 链接器配置与模块化在Publishing Settings部分Data Caching确保启用。这能利用IndexedDB缓存资源文件提升重复访问速度。但请牢记前面提到的Firefox iframe IndexedDB兼容性问题对于关键业务数据最好有备用的云端存储或提示机制。Decompression Fallback如果你的构建使用了Brotli或gzip压缩启用此选项。这允许Unity在浏览器不支持某种压缩格式时回退到未压缩的文件增加一层兼容性保障。Use Pre-built Engine如果多个页面使用相同版本的Unity WebGL引擎可以考虑使用此选项将引擎代码外部化、共享减少单个页面的加载量。但部署会更复杂需要确保外部引擎文件的路径正确。一个高级技巧模块化构建。对于大型项目不要把所有内容打成一个巨大的包。利用Unity的AssetBundles或Addressables系统将核心代码与资源分离。核心框架几MB快速加载并显示加载界面然后动态从服务器拉取资源。这不仅能极大改善Firefox下的首次加载体验避免单次内存申请过大也便于资源更新。3.3 图形API与质量设置在Player Settings - Resolution and Presentation以及Quality Settings中确保Default WebGL Graphics API是WebGL 2.0如果项目支持。WebGL 2.0有更好的性能和特性且现代浏览器包括Firefox支持良好。如果遇到极少数兼容性问题可以回退到WebGL 1.0但会损失一些效果。在Quality Settings中为WebGL平台单独配置一个质量等级。适当降低抗锯齿MSAA级别、阴影分辨率或纹理过滤模式。Firefox在某些硬件上的图形驱动开销可能略高适度的画质降级可以换来更稳定的帧率。4. 服务器部署与HTTP配置实战构建出来的文件需要正确的服务器环境才能跑起来。这是让Firefox“点头”的关键一步。4.1 必须配置的MIME类型你的Web服务器如Nginx, Apache, IIS或任何静态托管服务如Netlify, Vercel必须为Unity WebGL生成的文件扩展名添加正确的MIME类型。以下是Nginx配置示例server { # ... 其他配置 ... location / { # 确保目录索引正确通常指向包含 index.html 的文件夹 try_files $uri $uri/ /index.html; } # 关键的MIME类型设置 types { application/wasm wasm; application/octet-stream data; application/javascript js; application/x-javascript jslib; text/javascript mem; application/json unityweb; # 字体文件等 font/woff2 woff2; font/woff woff; application/vnd.ms-fontobject eot; font/ttf ttf; } }对于Apache可以在.htaccess文件中添加AddType application/wasm .wasm AddType application/octet-stream .data AddType application/javascript .js .jslib AddType application/json .unityweb AddType application/vnd.ms-fontobject .eot AddType font/ttf .ttf AddType font/woff .woff AddType font/woff2 .woff2为什么这么重要如果.wasm文件被当作普通的二进制流(application/octet-stream)发送Firefox可能无法正确识别并初始化WebAssembly模块导致运行时错误或直接失败。4.2 启用压缩与Brotli压缩能大幅减少传输体积加快加载。确保服务器启用了gzip和Brotli压缩。Brotli压缩率更高但需要浏览器支持。Firefox从版本44开始支持Brotli。Nginx配置示例需要安装ngx_brotli模块# Gzip压缩 (备用) gzip on; gzip_vary on; gzip_min_length 1024; gzip_types text/plain text/css text/xml text/javascript application/javascript application/xmlrss application/json application/wasm; # Brotli压缩 (更优) brotli on; brotli_comp_level 6; brotli_types text/plain text/css text/xml text/javascript application/javascript application/xmlrss application/json application/wasm;Unity在构建时如果检测到服务器支持Brotli会优先发送.br后缀的压缩文件。这能显著提升Firefox用户的加载速度。4.3 配置COOP/COEP安全头以启用高级特性为了使用多线程(WebAssembly Threads)和更好的性能需要在服务器响应头中添加add_header Cross-Origin-Opener-Policy same-origin; add_header Cross-Origin-Embedder-Policy require-corp;重要警告设置这些头之后你的页面将无法直接嵌入跨域的iframe也无法加载跨域资源如图片、脚本除非那些资源也明确允许被嵌入通过Cross-Origin-Resource-Policy头。你需要仔细评估你的资源加载策略。如果暂时用不到多线程可以不设置这些头以避免复杂的跨域问题。4.4 处理大型内存分配Content-Length与缓存对于大型的.data文件包含你的场景和资源确保服务器能正确返回Content-Length头。这有助于浏览器进行有效的资源调度。 此外为静态资源设置长期缓存利用浏览器缓存机制location ~* \.(wasm|data|js|jslib|unityweb|bundle)$ { expires 1y; add_header Cache-Control public, immutable; }immutable告诉浏览器只要URL不变该文件就永远不会改变可以放心使用本地缓存这对版本化部署非常有用。5. 前端HTML模板与加载脚本的定制Unity构建会生成一个index.html模板。直接使用这个模板可能不够健壮我们需要对其进行增强以更好地处理Firefox下的各种情况。5.1 增强的浏览器能力检测在head或加载脚本开始前添加一个环境检测函数script function checkBrowserCompatibility() { var issues []; var ua navigator.userAgent; var isFirefox typeof InstallTrigger ! undefined || ua.includes(Firefox); // 1. 检查WebGL支持 var canvas document.createElement(canvas); var gl canvas.getContext(webgl2) || canvas.getContext(webgl) || canvas.getContext(experimental-webgl); if (!gl) { issues.push(您的浏览器不支持WebGL。请升级浏览器或检查显卡驱动。); } // 2. 针对Firefox的特定版本检查例如对IndexedDB in iframe的检查 if (isFirefox) { var firefoxVersion ua.match(/Firefox\/(\d)/); if (firefoxVersion parseInt(firefoxVersion[1]) 43) { // 简单判断是否可能在iframe中 if (window.self ! window.top) { issues.push(您使用的Firefox版本较旧且在嵌入式页面中可能无法使用本地保存功能。建议升级Firefox至最新版。); } } // 可以添加更多Firefox特定检查 } // 3. 检查WebAssembly支持现代Unity默认需要 if (typeof WebAssembly ! object) { issues.push(您的浏览器不支持WebAssembly无法运行此内容。); } if (issues.length 0) { // 将错误信息显示在页面上而不是用alert阻塞 var errorDiv document.getElementById(custom-error) || (function(){ var div document.createElement(div); div.id custom-error; div.style.cssText position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); background:#f8d7da; color:#721c24; padding:20px; border-radius:5px; max-width:80%; z-index:1000;; document.body.appendChild(div); return div; })(); errorDiv.innerHTML h3兼容性检查未通过/h3ulli issues.join(/lili) /li/ul; return false; } return true; } // 在Unity加载器初始化前调用 if (!checkBrowserCompatibility()) { // 停止后续Unity加载逻辑 window.stopUnityLoad true; } /script5.2 优化Unity加载器配置修改模板中createUnityInstance的配置对象。以下是一些针对稳定性的关键参数var config { dataUrl: Build/YourGame.data.br, // 明确指定压缩格式如果服务器支持的话 frameworkUrl: Build/YourGame.framework.js.br, codeUrl: Build/YourGame.wasm.br, streamingAssetsUrl: StreamingAssets, companyName: YourCompany, productName: YourGame, productVersion: 1.0, // 关键配置启用缓存并指定缓存版本 cacheControl: immutable, // 内存初始化失败的重试策略非官方API需根据Unity版本调整此处为思路 // 有些社区方案会尝试在内存不足时提示用户并重试低画质版本 }; // 在加载失败时提供更友好的提示 createUnityInstance(canvas, config, (progress) { // 更新进度条... }).then((unityInstance) { console.log(Unity实例创建成功); // 可以在这里将实例赋给全局变量或开始游戏逻辑 }).catch((error) { console.error(Unity初始化失败:, error); var errorDiv document.getElementById(custom-error) || document.createElement(div); errorDiv.innerHTML h3加载失败/h3p游戏内容加载失败。请尝试br1. 刷新页面br2. 检查网络连接br3. 确保浏览器已启用JavaScript和WebGLbr错误详情 error.message /p; document.body.appendChild(errorDiv); // 可以在这里上报错误日志 });5.3 处理“白屏”或“黑屏”的加载占位符在Canvas前添加一个加载动画和进度显示确保用户在漫长的初始化过程中尤其是Firefox下可能更慢的Wasm编译阶段知道程序正在运行而不是已经卡死。div idloading-box styleposition: absolute; width:100%; height:100%; background: #333; color: white; display: flex; flex-direction: column; justify-content: center; align-items: center; z-index: 999; h2游戏加载中.../h2 div stylewidth: 50%; max-width: 400px; height: 20px; background: #555; border-radius: 10px; overflow: hidden; margin-top: 20px; div idprogress-bar styleheight:100%; width:0%; background: #4CAF50; transition: width 0.3s;/div /div p idprogress-text正在初始化.../p p idfirefox-tip stylefont-size: 0.9em; color: #aaa; margin-top: 30px; display: none;Firefox用户初次加载可能稍慢请耐心等待/p /div canvas idunity-canvas stylewidth: 100%; height: 100%;/canvas script // 在createUnityInstance的进度回调中更新 function onProgress(progress) { var bar document.getElementById(progress-bar); var text document.getElementById(progress-text); var percent Math.round(progress * 100); bar.style.width percent %; text.textContent 加载资源: percent %; // 如果检测到是Firefox且进度较慢显示提示 if (isFirefox progress 0.5 performance.now() 5000) { // 加载超过5秒且未到50% document.getElementById(firefox-tip).style.display block; } } // 加载完成后隐藏加载框 function onSuccess() { document.getElementById(loading-box).style.display none; } /script6. 常见问题排查与Firefox开发者工具使用指南当问题真的出现时有序的排查是解决问题的关键。Firefox的开发者工具按F12打开是你的主战场。6.1 问题现象与排查路径速查表问题现象可能原因排查步骤Firefox优先页面完全空白控制台无错误1. 脚本未加载路径错误2. 严重JS错误导致脚本中断3. 服务器返回非200状态码如403、4041.网络面板检查.html,.js,.wasm,.data等文件是否成功加载状态码200。2.控制台面板查看是否有红色错误即使被try-catch包裹也可能有警告。3. 查看页面源代码确认脚本标签的src路径是否正确。控制台报错TypeError: WebAssembly.instantiate...或failed to asynchronously prepare wasm1..wasm文件MIME类型错误或损坏2. 服务器CORS策略阻止加载3. 内存不足或初始化失败1.网络面板查看.wasm文件的响应头Content-Type必须是application/wasm。2. 检查控制台是否有CORS错误。3. 尝试减小“WebGL Memory Size”后重新构建测试。控制台报错WebGL: CONTEXT_LOST_WEBGL或 渲染突然停止1. 显卡驱动问题被列入黑名单2. GPU内存耗尽3. 图形指令过于复杂或存在Bug1. 在地址栏输入about:support检查“WebGL渲染器”是否被禁用。2.性能面板录制一段时间看是否有内存泄漏或异常高的绘制调用。3. 在Unity中简化场景降低画质看问题是否消失。游戏能运行但非常卡顿帧率低1. Firefox的WebGL实现在该硬件/驱动上效率低2. Unity项目未针对WebGL优化如大量GameObject.Update3. 浏览器后台标签页节流1.性能面板分析JS执行时间和渲染时间定位热点函数。2. 在Firefox的about:config中尝试切换webgl.enable-webgl2true/false看WebGL 1.0是否更流畅。3. 检查Unity ProfilerWebGL远程连接优化代码。本地存储PlayerPrefs不工作1. IndexedDB被禁用浏览器设置2. 运行在旧版Firefox的iframe中3. 隐私模式无痕浏览1. 在Firefox设置中搜索“IndexedDB”确保未被禁用。2. 检查浏览器控制台是否有IndexedDB相关错误。3.存储面板查看IndexedDB中是否存在Unity创建的数据表。加载进度条卡在某个百分比很久1. 某个大型资源如.data文件下载缓慢或阻塞2. Wasm编译/实例化耗时过长Firefox特点3. 同步的JS操作阻塞了主线程1.网络面板查看哪个资源加载时间TTFB, Content Download过长。2.性能面板录制加载过程看主线程在做什么。3. 考虑使用模块化AssetBundle拆分资源减少单次加载压力。6.2 Firefox开发者工具关键功能详解网络面板这是排查加载问题的核心。确保“禁用缓存”被勾选然后刷新页面。重点关注状态栏所有资源都应该是200或304。如果是404、403或CORS错误需要修正服务器配置。响应头点击某个资源尤其是.wasm,.data在“响应头”部分检查Content-Type、Content-Encoding是否为br或gzip以及Content-Length。时间线查看每个阶段的耗时阻塞、DNS查询、连接、SSL、发送、等待、接收。如果“等待”时间过长可能是服务器响应慢。控制台面板不要只看红色错误。黄色警告也常常包含重要信息比如“某些WebGL扩展不支持”、“同步XMLHttpRequest已弃用”等。这些警告在Firefox中可能比Chrome更早、更频繁地出现。存储面板在这里可以查看和操作IndexedDB。展开unity或你的游戏名可以看到用于存储PlayerPrefs和资源缓存的数据库。如果这里是空的而你的游戏试图保存数据那就证实了存储功能失效。性能面板点击录制按钮然后操作你的游戏再停止录制。你会得到一个详细的时间线显示主线程Main Thread上的所有活动JavaScript执行、样式计算、布局、绘制、合成等。如果游戏卡顿你通常能看到长的“JavaScript”任务块或频繁的“绘制”操作。这对于优化性能至关重要。about:config这是Firefox的高级配置页面。警告错误修改可能影响浏览器稳定性。你可以在这里搜索webgl找到诸如webgl.enable-webgl2、dom.indexedDB.enabled等选项进行强制启用或禁用用于诊断问题。例如如果怀疑是WebGL 2.0的问题可以将其设为false强制使用WebGL 1.0运行。6.3 实战调试案例解决“初始化很久”的问题假设你的游戏在Firefox上加载进度条到90%后卡住超过30秒然后才进入游戏。打开网络面板禁用缓存刷新。你发现一个巨大的.data文件比如500MB下载很快但之后浏览器似乎“卡住”了。切换到性能面板开始录制然后刷新页面。等待加载完成或卡住一段时间后停止录制。分析性能时间线。你可能会发现在下载完成后有一个非常长的**“JavaScript”任务**。放大这个任务查看其调用树。调用树可能指向一个名为(wasm-function[...])的函数消耗了大量时间。这基本确认了是WebAssembly模块的编译/实例化阶段耗时过长这是Firefox尤其是旧版本或低性能设备上的一个已知特点。解决方案优化构建进一步减少代码体积使用更激进的代码剥离Code Stripping移除未使用的引擎模块。使用Wasm Streaming Instantiation确保你的Unity版本较新2020.3 LTS或更新它默认使用了流式实例化可以边下载边编译改善感知速度。检查构建输出的.js加载器文件中是否使用了WebAssembly.instantiateStreaming。提示用户对于Firefox用户在加载界面显示“正在优化性能首次加载可能较慢请耐心等待”的提示。考虑使用asm.js回退在Unity构建设置中有一个“Compression Format”选项如果选择“Disabled”生成的是未压缩的代码。对于极端兼容性情况可以尝试此选项但文件体积会巨大。这不是推荐方案仅作为最后手段。7. 进阶策略监控、降级与自动化测试对于需要长期稳定运营的WebGL项目仅仅解决一次性问题是不够的需要建立机制。7.1 集成错误监控与上报在自定义的加载脚本和Unity内部通过Application.logMessageReceived捕获错误和异常并上报到你的服务器。这能帮助你在用户端发现那些难以在本地复现的兼容性问题。// 在HTML的加载脚本中 window.addEventListener(error, function(event) { // 上报 event.message, event.filename, event.lineno, event.colno console.error(全局错误捕获:, event); // 使用fetch或Image beacon上报 }); // 在Unity实例创建后可以从C#发送消息到JS或者用JS包装console.error var originalConsoleError console.error; console.error function(...args) { // 上报args originalConsoleError.apply(console, args); }; // 在Unity中你可以通过JSLib绑定一个函数让C#调用它来上报错误通过分析上报的数据你可能会发现“使用Firefox 78在特定Intel集成显卡上的用户崩溃率异常高”从而定位到特定的驱动兼容性问题。7.2 准备降级方案对于确实无法解决的兼容性问题如用户坚决不更新驱动或使用古董浏览器准备一个友好的降级页面是必要的。这可以是一个简单的2D HTML5版本的游戏介绍或者直接提示用户更换浏览器。通过之前提到的checkBrowserCompatibility()函数如果检测到致命的不支持特性如无WebGL可以重定向到一个unsupported.html页面而不是让用户面对白屏。7.3 建立自动化跨浏览器测试流程手动在每个浏览器和版本上测试是低效的。可以利用一些云测试服务如BrowserStack, Sauce Labs或使用Selenium等自动化工具将你的WebGL项目部署到测试服务器后自动在指定版本的Firefox、Chrome等浏览器中打开进行基本的加载、运行和截图对比测试确保核心功能在主流浏览器上正常工作。虽然WebGL内容的自动化交互测试比较复杂但至少可以实现“页面成功加载、不报致命错误、Canvas被正确渲染”这样的基础验证。这能在每次构建后给你一份基本的兼容性报告。说到底让Unity WebGL在Firefox上稳定运行是一个结合了正确构建配置、精准服务器部署、健壮前端代码和有效问题排查的系统工程。它没有一劳永逸的银弹但通过理解背后的原理建立清晰的排查思路并运用文中提到的这些工具和技巧你完全可以将这个“经典难题”的解决时间从几天缩短到几小时甚至提前避免大部分问题。