“Unity发布小游戏”这件事,在圈子里的热度一直不低。大多数开发者把目光放在微信、抖音这类头部平台,但某电商平台的小游戏其实是被低估的一个方向:它的用户基数大、支付链路短、电商场景天然适合休闲游戏和营销互动玩法,对团队来说是一个能快速验证商业变现能力的渠道。
这篇内容我打算把Unity开发者向该平台发布小游戏的完整链路拆开来讲。从工程配置、代码兼容、资源优化,到登录支付接入、提审规范和上线后的迭代,每个环节都会给出我实际踩过坑之后沉淀下来的做法。如果你是第一次接触小游戏容器化发布,或者已经在做但总被一些诡异问题卡住,这篇可以帮你把整体的流程走通。
1. 项目全貌:Unity小游戏是怎么一回事
1.1 小游戏平台的运行模式
很多人第一次听说“用Unity做小游戏”时,脑子里先冒出来的是传统手游那套开发流程。实际上小游戏走的完全是另一条路:你开发的Unity工程,最终会被构建成WebGL格式的输出包,再经过平台提供的转换工具,打包成一个可以被宿主App内嵌容器运行的字节码文件。
这个容器本质上是一个定制过的JavaScript运行时,它给Unity的WebGL产物提供了基础的系统调用接口,包括文件读写、网络请求、触摸事件、音频播放、设备振动等能力。Unity侧写好的C#逻辑被IL2CPP编译成C++,再通过Emscripten交叉编译成WebAssembly,配合一份JavaScript胶水代码在容器中运行。
也就是说,你在Windows上开发时用的文件系统、线程、反射这些底层能力,在小游戏环境里有一部分是缺失或被替换的。理解了这一层,后面遇到的所有兼容性问题就都能解释通了:不是你的代码写错了,而是Unity原本假设的运行环境和小游戏容器提供的环境之间存在差异。
1.2 为什么选择Unity来做小游戏
该电商平台小游戏支持的技术栈不止Unity一种,也有原生JavaScript、Cocos等方案。但Unity在这个场景下有几个优势是明显的。
第一,团队复用。很多做手游的团队已经积累了成熟的Unity管线,包括渲染框架、资源组织方式、UI系统和动画系统。用Unity做小游戏,美术资产、工具链、团队技能都可以完整复用,迁移成本远低于换引擎重写。
第二,表现力上限。Unity的渲染能力、粒子特效、后处理效果和材质体系比纯JS方案强很多。电商场景里常见的“3D扭蛋”“虚拟试戴”“养成互动”这类营销玩法,用Unity做出来的视觉质感明显更高级,转化率也更好。
第三,跨端一致性。Unity构建一次WebGL包,理论上可以适配多个支持该运行时的小游戏平台。虽然每个平台都有SDK细节差异,但核心的渲染逻辑、游戏逻辑是通用的,后期多平台分发时性价比很高。
当然,选Unity也要接受它的代价:包体比JS方案大、加载时间长、内存占用高、调试链路复杂。所以并不是“Unity一定最好”,而是“如果你的团队本来就在用Unity,这个方案最平滑”。
2. 游戏外的环境准备与工程配置
2.1 环境安装与SDK接入
动手之前,先把开发环境收拾利索。需要准备的东西包括:
- Unity编辑器,我目前主力用的是2021 LTS版本,2022 LTS也能用,不建议用较老的版本,部分API和WebGL构建行为差异比较大。
- 对应平台的小游戏转换工具,这个工具负责把Unity构建出的WebGL目录转换成小游戏项目结构,并生成接入平台的配置文件。
- 平台的开发者账号,需要在后台创建应用并拿到AppID和AppSecret,后续登录、支付、云调用都会用到。
工具装好之后,要先在Unity工程里导入平台官方提供的SDK包。SDK的核心作用是在Unity C#侧暴露一套接口,封装了与宿主机器的JSBridge通信逻辑。它内部做的事情就是通过Application.ExternalCall或者SendMessage这类机制,从C#调用JavaScript函数,再在回调中把宿主返回的数据传回Unity。
这里有个容易忽略的细节:SDK接入后要先在平台后台把应用的“游戏类目”和“运行权限”配置好,否则在真机调试时会遇到域名校验失败、登录接口被拒之类的问题。我一开始就吃过这个亏,代码里查了半天,最后发现是后台配置漏了一个接口权限。
2.2 工程参数与构建配置
SDK接入之后,重头戏是工程设置。小游戏对WebGL构建的参数有硬性要求,配置不对,转换工具直接报错。
第一步,切换构建平台。在Build Settings里把目标平台切到WebGL,这一步没什么好说的。
第二步,配置Player Settings。有几个关键项:
| 配置项 | 推荐值 | 说明 |
|---|---|---|
| Scripting Backend | IL2CPP | 这是硬性要求,Mono在小游戏容器里跑不起来 |
| Compression Format | Brotli | 包体小、解压快,小游戏环境适配良好 |
| Strip Engine Code | 开启 | 能砍掉用不到的引擎模块,显著缩小包体 |
| Managed Stripping Level | Medium起步 | 根据实际运行情况调,High容易误删反射调用的代码 |
| Player Log | 开启 | 方便真机调试时抓日志 |
| Auto Graphics API | 保持默认 | 小游戏容器内WebGL2/1切换由运行时自动处理 |
| Color Space | Gamma | 部分平台的WebGL实现和线性空间配合有问题,建议先用Gamma跑通,后续再视表现优化 |
第三步,处理裁剪和AOT。IL2CPP编译的一个特点是会裁剪掉“看起来没被引用”的托管代码。如果你的代码里用了反射、typeof查询、动态创建类型等能力,必须在代码里显式声明引用,或者在link.xml里配置需要保留的类型。这一类问题非常隐蔽,构建时完全正常,运行到某个业务逻辑时才抛TypeLoadException,排查起来极其费劲。
可以提前做的事是:写一个link.xml放在Assets目录下,把项目中所有用反射访问的类、第三方SDK里的类型都保留进来。宁可稍微多保留一点增加包体,也不要上线后某个功能在特定机型上突然崩溃。
2.3 代码与API兼容性改造
构建配置只是第一步,代码层面的兼容性改造才是真正决定你能不能跑起来的关键。
首先要处理的是文件系统访问。小游戏容器没有传统意义上的本地文件目录,System.IO.File、Directory这些接口基本不可用。如果你在初始化时用了StreamingAssets下的文件,必须换方案:要么把文件内容编译进AssetBundle,要么放到远程服务器按需加载。PlayerPrefs是支持持久化存储的,适合保存小体量的存档数据。
其次是多线程限制。Unity开发时习惯开线程做加载、计算、网络等任务,但WebAssembly的线程支持取决于浏览器和容器实现,在很多低端Android机器上会直接崩溃。制造的规则是:不要自己创建Thread,不要用ThreadPool做耗时操作。数据量小的解析工作放在同步代码里执行,数据量大的任务拆成协程分帧处理,或者用Unity的Job System,让引擎来管理线程。
再次是反射和代码生成。刚才提到了IL2CPP裁剪,其实还有一层限制:小游戏环境对System.Reflection.Emit是明令禁止的,它需要在运行时动态生成IL代码,这在WebAssembly环境下根本无法工作。凡是依赖动态代理、动态生成的库(部分JSON序列化库、ORM框架、AOP框架),基本都要换成AOT友好的替代品。比较稳妥的JSON方案是Newtonsoft Json的纯兼容模式,或者直接用Unity自带的JsonUtility,后者性能好但类型限制较多。
还有网络请求也要统一。编辑器里用HttpWebRequest可能没问题,到了小游戏环境必须改用UnityWebRequest。而且小游戏平台对网络请求有域名白名单校验,你在代码里请求的CDN地址必须先在平台后台配置成合法域名,否则线上请求会被拦截,日志里报的就是一串奇怪的ERR_NAME_NOT_RESOLVED。
3. 资源、界面与设备适配
3.1 首包大小与资源加载设计
小游戏平台对包体体积有严格的限制。主包通常需要控制在几MB以内,超过就要走分包或者远程资源方案。这里的“包体”指的是转换工具生成出来的实际发布包,不是Unity编辑器里的工程大小,建议养成随时查看最终包体积的习惯。
首包的压缩策略有优先级:
第一,删冗余资源。很多美术资产导入Unity时没有做压缩设置,比如PNG纹理没有改成压缩格式,音频还是WAV。使用Asset Hunter这类工具能快速扫出没有被场景引用的残留资源,清理后包体往往能降30%以上。
第二,调好纹理压缩格式。WebGL场景里,移动端纹理压缩首选ASTC,但低端安卓机未必支持,所以要保留ETC2的降级方案。做法是使用Unity的Texture Import Settings,为主机和移动端分别设置压缩格式,配合小游戏容器提供的纹理上传方式,尽量减小GpuMemory占用。
第三,避免把所有逻辑代码打到一个包。用小游戏平台的分包能力,把新手引导、活动玩法、抽奖动画这类非核心内容拆分到独立的分包中,用户打开首屏时只需要下载核心逻辑。我做过的一个3D展示项目,核心包从12MB压缩到4.8MB,启动速度明显改善。
第四,远程资源走CDN。美术图集、音频、AB包全部放到CDN上,在游戏启动后动态加载。有个注意点:CDN必须开启跨域资源共享(CORS)配置,否则UnityWebRequest加载远程资源会被容器拦截。我当时踩这个坑时,在后台CDN配置里加了Access-Control-Allow-Origin响应头,问题才解决。
3.2 屏幕适配与安全区
小游戏跑在宿主App的WebView容器里,屏幕情况比原生手游更复杂。宿主App可能有自己的导航栏、底部tab栏,小游戏只占据中间的一段区域。Unity的默认分辨率设置如果不对,游戏画面会被拉变形或者显示不全。
比较靠谱的做法是:启动时通过平台SDK获取实时的视口尺寸和屏幕安全区信息,然后动态调整Unity的屏幕分辨率。具体代码逻辑是先把SDK返回的视口宽高转换成逻辑分辨率,再调用Screen.SetResolution设置到引擎。
这里有一个设计上的取舍:UI布局不要全部用绝对坐标,尽量使用Anchor锚点系统和Canvas Scaler来适配不同比例的屏幕。电商App里顶部有搜索栏、底部有导航栏,游戏区域通常是竖屏比例,如果你做的游戏是横屏玩法,要提前和平台确认是否支持横屏API,否则只能按竖屏设计。
刘海屏和挖孔屏也是个老问题。摄像头遮挡游戏按钮在真机测试时非常明显,我现在的做法是把核心交互按钮全部约束在安全区之内,通过读取平台SDK返回的safeAreaInsets,动态调整Canvas里的安全区域偏移量。之前有个版本没处理这个,用户反馈“右边按钮点不到”,排查之后发现是传感器区域正好遮住了答题按钮。
3.3 生命周期、音频与网络处理
Unity的OnApplicationFocus、OnApplicationPause回调在小游戏环境里依然有效,但触发时机和原生App有些差异。用户从游戏切到宿主App的电商页面再回来,这个过程会触发焦点丢失和重新获得的回调。如果你的游戏有挂机收益、倒计时逻辑,一定要在这个回调里做时间校准,否则可能出现“切走10分钟回来收益涨了2小时”的乌龙。
音频方面要注意两个坑。
第一,WebGL的音频上下文初始状态往往是暂停的,必须等到用户第一次触摸屏幕后调用AudioListener.pause = false或者直接播放一次音效,才能解除浏览器的自动播放限制。我建议做一个“点击任意处开始游戏”的界面,在用户点击事件里完成音频初始化,一举两得。
第二,音频格式选择。小游戏环境对音频解码的支持取决于宿主版本,MP3和AAC基本通用,但某些低端机型对WAV、OGG的支持不稳定。最稳妥的做法是全平台启用MP3压缩格式,重要音效保留一份原生格式做降级。
网络请求在小游戏环境里要特别注意超时和重试策略。移动网络环境波动大,CDN资源下载失败的概率比PC高得多。核心做法是两点:所有远程加载都设置超时时间,并在失败时自动重试三次;首屏的关键资源(启动图、核心AB包)在本地做好缓存,即使网络差也能保证游戏可启动、可在缓存范围内游玩。
4. 平台能力接入:登录、支付、分享与广告
4.1 平台Bridge能力调用思路
小游戏和普通H5游戏的核心区别在于:它能调用宿主App的底层能力,完成登录、支付、社交分享、广告等操作。但这些能力不能直接从Unity调用,必须走“C# -> JSBridge -> 宿主Native -> 平台服务端”的长链路。
平台SDK在Unity侧提供的方法是异步的,调用后立刻返回,结果通过回调函数通知。比如登录流程:C#代码调用SDK的登录接口,SDK内部通过JSBridge调用宿主App的登录能力,宿主App完成授权后把临时票据返回给SDK,SDK再通过回调把票据传给Unity侧,Unity侧拿票据去自己的游戏服务器换会话凭证。
理解这个调用模型很重要,它能帮你避免很多设计误区。比如不要在Awake里直接调登录接口然后立刻读取用户ID——回调还没回来,读到的一定是默认值。正确的做法是把状态机管理起来:启动阶段加载基础资源的同时做登录,登录完成后再进入主菜单逻辑。
4.2 登录与用户信息获取流程
登录是整个平台能力接入的基础,业务流程上和传统手游类似,但有几个平台特有的细节。
第一步,在平台后台配置回调域名和授权能力。没配置的话,开发环境能跑通,上线后真机调用登录接口会直接报权限不足。
第二步,在Unity侧调用登录接口,拿到临时的授权Code,这个Code的有效期很短,需要立即发送给游戏自有的服务端。
第三步,游戏服务端拿着Code调用平台服务端的登录接口,换取用户的OpenID和SessionKey。OpenID是用户在当前应用下的唯一标识,SessionKey用于后续解密手机号、用户信息等敏感数据。
第四步,登录完成后,如果业务需要展示用户昵称头像,需要调用平台提供的“获取用户信息”接口,这块必须走平台授权弹窗,不能静默获取。而且平台对敏感信息的展示有规范,昵称、头像这些拿到后要在自己的服务器缓存,避免频繁调用接口触发限流。
我见过很多团队在登录环节犯一个错:把登录Code直接暴露给第三方统计SDK,或者把OpenID拼在URL参数里。这属于敏感信息管理不规范,平台审核时对这类问题查得很严。合规做法是Code只在Unity侧和服务端之间传递一次,所有后续业务请求都用服务端签发的会话Token。
4.3 支付与订单流程
电商平台小游戏最大的吸引力就是支付链路短。但支付接入的复杂度并不低,需要先弄清楚流程。
用户点击“购买道具”按钮后,Unity侧调用SDK的创建订单接口,把商品ID、数量、游戏服务器订单号这些参数传过去。平台会拉起宿主App的收银台,用户完成支付后,平台服务端会向游戏服务端的回调地址发送支付结果通知。
游戏服务端必须做两件事:验证回调签名,确认订单真实有效;执行发货逻辑——把道具发放到用户账户。这里有一条铁律:任何以客户端返回结果为准的发货逻辑都不可信,一定要以服务端收到的支付回调为准。否则改一下客户端请求就能刷道具,线上会出严重事故。
调试支付时有个实用技巧:平台后台一般有“测试白名单”功能,把测试账号加进白名单后,单笔支付金额可以设成0.01元甚至免支付,方便反复验流程。我建议测试环境单独配一个回调地址,和线上的分开,避免测试订单污染线上发货数据。
4.4 分享裂变和广告变现
分享功能是营销向小游戏的核心增长手段。Unity侧接分享时,需要留意分享素材的配置:分享标题、分享图片、分享路径都要提前准备。分享图片的尺寸要按平台规范来,否则会出现图片被裁切的情况。
广告变现这块,平台主要提供插屏广告和激励视频广告。激励视频的场景设计要克制,建议在玩家主动选择“复活”“加时”“领双倍奖励”这类正向交互时弹出,尽量避免硬插播。插屏广告则要选好时机,一般放在关卡结束、游戏切后台的时间点,避免在用户操作过程中突然弹出导致误触。
广告SDK接入的坑主要在于回调时机。广告播放完成的回调里不能直接发放奖励,要等平台SDK确认播放有效后再发,否则用户中途关闭广告也可能触发奖励发放。我现在的做法是:收到播放成功回调后,再向自己的服务端发起一笔奖励发放请求,服务端做幂等处理,防止重复发放。
5. 构建、上传、提审与发布
5.1 完整发布流程
从Unity构建到小游戏上线,整个流程我梳理成下面这步路子,照着走基本不会漏。
第一步,在Unity里做一次干净的WebGL Build。确保输出目录没有旧文件,构建完成后检查Build文件夹下的index.html、js、wasm等文件都齐全。构建时可以开启Build Report面板看体积分布,这个信息对后续优化很有用。
第二步,使用平台提供的转换工具,选择Unity构建输出目录,工具会自动生成一个小游戏项目目录,里面包含了game.js、game.json等平台要求的配置文件。
第三步,配置game.json。这个文件里要声明小游戏的页面路由、窗口角度、分包信息、预载资源列表等。尤其注意deviceOrientation配置,竖屏填portrait,横屏填landscape,填错了游戏画面会整体旋转90度。
第四步,用平台的开发者工具打开转换生成的项目目录,进行本地预览。开发者工具会模拟宿主App的环境,能看到真实的加载效果和报错日志。在真机预览之前,先用这个工具排查大部分基础问题。
第五步,真机预览。扫码在手机上跑一次完整流程,重点测试登录、支付、分享、广告、音频这些宿主能力,以及弱网环境下的资源加载表现。
第六步,上传代码到平台后台,提交审核。后台需要填写版本号、更新说明、隐私声明等信息,等审核通过后,点击发布按钮正式上线。
5.2 审核材料与常见退回原因
提审被驳回是常态,不用气馁。根据我的经验,驳回原因集中在以下几类。
第一类是内容合规问题。游戏内文案不能出现夸大宣传、诱导分享、封建迷信或者违规抽奖相关内容。电商平台对营销活动尤其严格,像“转发必得”“分享返现”这类诱导性文案基本一票否决。
第二类是隐私合规问题。如果游戏收集了用户信息(比如通过登录接口获取手机号),必须在提审材料中明确说明数据用途,并且在游戏内提供隐私政策入口。我们之前一个项目漏掉了隐私弹窗,审核那边打回来一次,补上之后才通过。
第三类是包体或性能规范问题。启动时间是审核的重点关注项,如果游戏启动白屏时间过长,审核人员会直接判定不合格。我遇到过一次因为首屏加载了过大的启动图导致启动时间超标,压缩图片后解决。
第四类是素材合规问题。应用图标、启动图、分享图都有尺寸和内容规范,不能用代码截图、不能出现第三方品牌logo、不能有明显的水印。
建议在正式提审前,自己对照平台最新的审核指南做一次自测,把容易踩的雷提前排掉。毕竟一次审核周期通常要一两天,来回被驳回会严重拖慢项目进度。
6. 高频Bug与调试实录
6.1 白屏、首屏加载失败
白屏是所有Unity小游戏开发者最头疼的问题,没有之一。它的原因可能有一长串,但如果按照顺序排查,效率会高很多。
先看开发者工具里的console日志。如果日志显示加载wasm失败,多半是CDN跨域配置问题,检查是否加了CORS头。如果日志显示JS异常,重点看SDK初始化代码有没有在platform准备好之前被调用。
再看网络请求面板。确认资源文件都成功拉取,特别是主包里的核心数据。有时候白屏是本地预览正常、真机白屏,这种大多是域名白名单问题——本地工具默认关闭校验,真机强制开启。
还要检查game.js入口代码。转换工具生成的框架代码一般不会出错,但如果你手改过入口文件,比如自己加了一段初始化逻辑,那就得确认它在容器内的执行顺序。我踩过的一个坑是:在入口处同步调用了登录接口,而登录SDK还没完全初始化,导致后续流程全部挂起,表现就是白屏。
6.2 反射裁掉、功能出不全
这种问题最迷惑的地方在于:编辑器里一切正常,构建包也能打开,但进入某个页面就报错,控制台输出一条MissingMethodException或者ExecutionEngineException。遇到这种报错,第一反应应该是IL2CPP代码裁剪,你用到的方法或类型在裁剪过程中被移除了。
解决办法有几个路径。先用上文的link.xml把涉及反射、序列化、第三方扩展的类显式保留下来。如果保留下依然报错,可能是泛型方法被裁剪,需要在代码里加入对应泛型类型的实际调用代码,或者用UnityEngine.Scripting.Preserve特性标注方法。
还有一种情况:你用到了某个第三方库,但它内部大量使用反射,在小游戏环境里反射性能本来就差,加上裁剪问题,几乎跑不起来。这种就建议直接换库,别花时间硬适配。比如某些复杂的JSON序列化库,换成JsonUtility之后问题自然消失。
6.3 音频与震动失效
音频失效绝大多数是自动播放策略导致的。检查确认用户已经有一次真实的触摸交互,并且交互事件里完成音频恢复逻辑。如果用户第一次点击事件被SDK拦截(比如错误处理弹窗拦截了点击),也会导致音频起不来。可以在OnEnable里加一个音频状态打印,快速定位是不是被拦截。
震动失效则要区分平台:iOS端对震动API的限制比安卓严格,部分平台在iOS上不支持任意调用的震动能力,只能在该平台明确规定的声音震动接口里操作。开发前先查平台文档里vibrate接口的机型兼容列表,不要假设所有机型都支持。
另外,震动和音效的配合也有讲究。每次震动调用之间记得加一个100毫秒左右的间隔,避免连续短震动在部分Android机型上触发系统级节电策略导致后续震动全部失效。
6.4 内存与崩溃问题
小游戏环境给Unity分配的内存是有上限的,低端安卓机上尤其紧张。内存溢出通常表现为两种情况:突然闪退、或者画面卡死然后被容器强杀。iOS上往往是闪退,Android上往往是黑屏卡住。
常用的排查手段:开启Unity的Profiler窗口,用远程调试模式跑真机,实时观察内存占用曲线。当纹理内存占用异常增长时,八成是AssetBundle没及时释放,检查代码中所有Instantiate创建的Asset实例有没有配套的Resources.UnloadUnusedAssets调用。
一个非常容易被忽视的点:日志打印本身也涉及字符串拼接和堆分配,在循环逻辑里频繁打印日志,短时间内容器内存会快速上涨。生产环境的Debug.Log调用要关闭或精简,Release模式不要保留大量开发日志。
如果内存实在紧张,可以考虑降低纹理质量选项,减少相机后处理特效,将动态合批改为静态合批。这些优化手段虽然不能根治内存问题,但能把可用内存余量提上来,减少在低端机上的崩溃概率。
6.5 iOS与Android真机表现不一致
同一个包在iOS和Android上表现出差异,不是玄学,而是两个平台的底层实现本来就不同。最常见的不一致是字体渲染:iOS的中文字体渲染效果通常比Android细腻,但在部分Android机型上会出现字体发虚、缺字、字形不一致。解决办法是不要依赖Unity的默认字体,显式加载一个中文字体文件,并配置好字体动态加载的atlas大小。
另一个高频差异是触摸响应。iOS对触摸事件的响应普遍比Android更灵敏,同样的点击区域在Android上可能显得“迟钝”或“容易误触”。测试时要重点验证最小可点击区域,平台规范里通常会对按钮的点击区域有最小尺寸要求,太小的话iOS能点到、Android会漏点。
还有渲染表现的差异。部分Android机型的GPU对Shader的支持不全,自定义Shader在iOS上正常,到Android上出现花屏或全部渲染为粉色。遇到这个问题,优先检查Shader的精度指令和是否用了高精度的转义写法,或者直接使用Unity内置的标准化Shader(比如Mobile/Diffuse、UI/Default这类),在兼容性上更稳妥。
7. 上线后运营与版本迭代
7.1 数据看板与性能监控
游戏上线不是终点,而是一个新的起点。小游戏平台的运营后台通常会提供用户留存、活跃、付费、分享裂变等核心数据指标。这些指标的价值在于帮你验证玩法设计是否成立、经济系统是否合理。
除了运营数据,性能数据同样重要。平台一般会提供崩溃率、卡顿率、加载耗时等指标。我建议把首屏加载耗时和崩溃率设为监控红线,这两项直接决定用户的去留。加载超过5秒,用户流失率会直线飙升;一个崩溃率超过1%的版本,必须优先处理再迭代新功能,否则辛苦拉来的用户全在第一步流失。
如果平台支持上报自定义日志,建议在游戏内埋点几个关键事件:登录成功、首局开始、支付完成、分享点击、广告播放。通过事件漏斗,你能直观看到用户在哪一步流失最多,这个信息比看汇总数据有用得多。
7.2 远程资源更新与版本迭代策略
小游戏的一个优势是可以做到“不发版就更新资源”。借助AssetBundle和CDN,你可以在不通过审核的情况下远程更新美术资源、数值配置、关卡内容。重要提示是:代码逻辑不能热更,任何涉及C#逻辑的改动都必须走全量发版。
我的资源热更方案大概是这样的:启动时从CDN拉一份资源版本清单,和本地缓存的清单对比,有差异就下载新资源并更新本地缓存。资源文件的命名用内容哈希值,这样文件名改变就代表内容改变,避免缓存污染。
代码发版的核心是节奏。小步快跑、频繁发版不是好方案,但也不要攒一堆改动憋大招。我倾向于每周固定一个发版窗口,把本周的Bug修复和优化集中提交审核。电商平台的用户群体对稳定性要求高,宁可少出新功能也要保证每次更新没有明显的体验回退。
还有个小技巧:每次发版前,保留一个“灰度包”,在后台设置一小部分流量先预览新版,观察崩溃率数据没问题后再全量放量。这个流程虽然多花一点时间,但能帮你挡住大多数线上事故。
8. 发布过程中的几个习惯性操作
最后分享几个我在多个项目里反复用到的小习惯,算不上什么高深技巧,但关键时刻能省很多时间。
第一,每次构建前先在命令行做一次增量资源盘点。对比上一次构建的资源文件列表,能提前发现有没有引入超大资源、有没有误删核心配置。这种自查几秒钟就能完成,但能避免构建完成后才发现问题的返工。
第二,保留一份“最小构建包”的备份。就是那个只包含空场景、没有任何业务逻辑的Unity工程配置,当你怀疑某个问题是你自己代码导致的时候,用最小包验证一下是不是引擎或工具链本身的问题,定位效率极高。
第三,所有平台SDK调用都包一层自己的封装类,不要直接在业务代码里散漫地调用SDK接口。封装的好处是:当平台更新SDK接口或加权限校验时,你只需要改封装类一个地方,不用全工程搜索替换。
第四,支付回调、登录回调这些涉及服务端数据处理的地方,Unity侧代码里一定要打印完整的回调参数。这个习惯帮我定位过好多次线上问题,虽然日志看起来繁琐,但出了问题能直接翻日志确认是客户端没调对还是服务端返回异常。
第五,真机测试时准备一台配置偏低的Android手机作为最低标准测试机。开发阶段大部分问题在模拟器和高端机上都看不出来,低端机一跑,渲染兼容、内存上限、触摸灵敏度的问题全都暴露出来。测试设备不需要多新,能用就行,但它能代表的用户群体比热门旗舰机重要得多。
做Unity小游戏发布,整体上没有手游发行那么复杂,但坑很细、很碎。核心思路就是先把WebGL构建链路跑通,再把平台能力逐项接入,最后用真机测试兜底。按照这个顺序走,你会发现在平台上架一款Unity小游戏,其实并没有想象中那么难。