ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Unity序列帧导出全指南:Recorder与Timeline实现透明通道动画输出

Unity序列帧导出全指南:Recorder与Timeline实现透明通道动画输出 前几天帮一个朋友排查序列帧输出问题他折腾了一整天录出来的动画带黑底拿到AE里抠了半天还是带一圈灰边。我远程看了一眼他的Recorder设置问题其实很简单透明通道压根没开对。这个场景在Unity项目里太常见了。无论是给视频组交付宣传素材、给微信小游戏做UI特效、还是给策划批量生成动画预览图序列帧都是绕不开的一环。而RecorderTimeline这套组合是目前我用下来最稳、最可控、也最省人力的方案。这篇就系统讲一遍从Recorder和Timeline的搭配、透明通道的底层原理到具体的输出设置、常见坑位和后期优化全按实际项目里能落地的流程来写。不管你是刚开始用Recorder的新手还是已经被序列帧折腾过几轮的熟手应该都能找到点有用的东西。1. 序列帧需求从哪来动画复用与跨平台交付的现实场景先说个反直觉的事实序列帧不但没过时在移动端、Web端、UI特效和视频后期里反而用得比几年前更频繁。我做过的项目里序列帧需求基本能分成四类。第一类是视频合成和后期包装素材比如游戏宣传片、广告素材、活动视频里需要把Unity里的角色动作或特效镜头导成带透明通道的PNG序列丢到AE或PR里继续调色、叠字、合成。这类需求通常是美术或视频组提的要的是画面干净、帧率稳定、带Alpha。第二类是游戏内的UI和玩法动画。角色立绘的呼吸动画、卡牌特效、待机动作、打击爆点、加载动画团队不一定愿意上实时粒子和模型因为Shader复杂度、后处理开销、内存波动在真机上不可控。烘焙成序列帧后运行时只是逐张贴图切换性能开销完全是明牌真机好不好跑心里有底。第三类是跨平台兼容问题。微信小游戏、小程序、WebGL这些环境对Shader和透明视频的兼容性参差不齐同一套特效在PC编辑器里好好的一上安卓真机就可能黑屏、花屏、边缘各种毛刺。序列帧是彻底的“笨办法”但也是彻底的“安全办法”只要内存给得起哪里都能跑。第四类是动画资产预览与管理。项目里几十个动画状态需要把每个动作烘焙出一段缩略序列帧放进编辑器或后台系统里当预览图用。这种情况下你要的不是单张截图而是批量输出小分辨率、固定帧数、命名规范的序列帧。为什么这些需求都绕不开RecorderTimeline组合我自己的体会是四个原因。一是帧率完全可控。Recorder按设置的帧率逐帧采样不丢帧、不撕裂、不闪屏比从Game View录屏或OBS抓屏稳定太多。二是输出格式天然带Alpha。PNG Sequence直接输出透明通道录屏软件做不到这一点后期抠像又必然带边缘脏点。三是时间轴可编程。Timeline把角色动画、摄像机运动、特效开关全部放在一条时间线上Recorder按帧精确驱动想录第0到30帧就录第0到30帧不会有任何状态偏移。四是可以批量集成。通过Editor工具或命令行参数能让Recorder在打包机上自动跑不用人肉守着窗口点按钮。做个直白对比供你评估方案方案帧稳定性透明通道批量能力精确帧范围推荐度录屏软件OBS等中等无弱不精确低绿幕录制后期抠像中等需抠像弱不精确低Unity RecorderPNG高原生支持强精确到帧高程序化RenderTexture导出高支持强完全可控高需写代码如果你是被视频组或策划追着要序列帧的那类人早点把Recorder这套流程跑通后面能省掉大量返工。2. 环境准备Recorder版本选择与Timeline时间轴搭建先讲环境。Recorder这个插件在Unity里直接通过Package Manager安装Window菜单搜索Recorder就能找到包名是com.unity.recorder。这里有个版本细节需要注意Unity 2019/2020时代的Recorder是2.x界面和现在的4.x/5.x差异很大很多老教程已经对不上了。Unity 2021以上版本Recorder 3.x开始支持Timeline集成4.x之后又加入了无限录制等能力我一直建议直接用当前Editor版本匹配的最新版别为了守着旧教程而锁旧版本。安装完成后菜单栏会多出Window General Recorder或者新版直接是Window Recorder。打开后是一个独立的Recorder窗口所有录制配置都从这里进。Timeline的搭建是这样的场景里创建一个空物体挂上PlayableDirector组件新建一个Timeline Asset拖给它。然后在Timeline窗口里创建Animation Track把带Animator的角色模型拖进轨道动画片段会自动吸附到时间轴上。如果要做摄像机运动需要把摄像机也拖进Timeline创建Camera Track或者用Cinemachine Track在时间轴上给位置、旋转、FOV打关键帧。粒子特效、音效、AnimationClip、Activation Track都可以挂在同一条时间线上。这里我强调一个逻辑Timeline在序列帧录制里真正扮演的角色是“确定性驱动器”。没有Timeline的时候Recorder是直接推场景播放动画从哪个状态开始、播到哪一帧、特效触发时机对不对全看运气。有Timeline后一切状态都收敛到时间轴上Recorder只需要按帧驱动PlayableDirector就等于驱动了整个场景。这也是为什么我建议哪怕只有一个角色待机动画也先给它建一个Timeline。搭建过程中还有几个细节容易忽略。第一摄像机最好单独建一个专门用于录制的Camera不要在录制场景里复用战斗或UI的跟随摄像机避免被脚本、输入系统干扰。第二如果要用正交摄像机录制2D风格序列帧Orthographic的角度和大小需要预先估计好这个后面我会专门讲包围盒自动适配的问题。第三录制用的场景建议把不必要的反射探头、LightProbe、后处理Volume、背景物体全部隐藏或删除场景越干净渲染越稳定。还有一个新手特别容易踩的坑直接在Game View里测试了一下动画然后忘记恢复PlayableDirector的进度正式录制时发现第一帧是歪的。我的习惯是每次开始录制前先在Timeline窗口把播放头拖到第0帧确认一下起始状态再点Recorder的Start。这几十秒的确认能省下整段重录的时间。3. 透明通道的底层原理为什么你录出来永远是黑底或白底透明序列帧的核心不止是Recorder选项更在于搞懂为什么很多项目弄了半天录出来还是黑底或者白底。先理解渲染管线和Alpha通道的关系。摄像机渲染一帧画面时每个像素都包含RGBA四个分量最后两个字母A就是Alpha透明度。Recorder把帧保存为PNG时会把这四个通道一并写入文件。问题是场景里背景到底给Alpha通道输出的是什么。默认情况下摄像机的Clear Flags是Skybox或者Solid Color背景色Alpha通常等于1完全不透明。场景里的物体如果材质不透明它的Alpha通道也会被写入1。最后得到的PNG自然是完全不透明的。透明通道要成立必须同时满足两个条件背景的Alpha必须是0物体材质必须输出正确的Alpha。Unity Recorder在录制设置为Targeted Camera时提供了透明选项新版本里通常叫Transparent或Include Alpha勾上之后Recorder会创建一个带Alpha通道的渲染目标并把背景Alpha清成0。到这里背景透明的问题解决了。但如果物体的Shader不输出Alpha比如用的内置默认Standard材质、Lit材质它们会把不透明的Alpha写进渲染目标那么角色周围依然是矩形色块等于白录。另一个极具迷惑性的问题是PNG文件在Windows文件管理器、或者大部分浏览器里透明部分会被显示成黑色。很多人一看到黑底就以为录制失败其实把图片拖进Photoshop或AE里关掉白色背景图层透明区域是完全正常的。这个误判我见过太多次先确定这个再开始排查。有一种妥协方案是用绿幕或蓝幕录制后期用键控把背景抠掉。坦白说这个方案在Unity里很难做到高质量因为实时渲染的边缘抗锯齿、半透明粒子、角色头发丝键控之后全是半透明残留。与其后期修边缘修到崩溃不如一开始就走透明通道管线。排查透明问题按这个顺序来现象原因解决办法输出PNG显示黑底预览陷阱或摄像机Clear Color不透明用PS/AE打开确认把背景Alpha设为0完全没有Alpha信息没勾透明相关选项或材质不透明勾选Transparent替换为透明Shader角色边缘有白边/灰边贴图半透明边缘与背景混合材质Queue设为Transparent关闭ZWriteURP下仍然不透明URP的Lit默认输出不透明改用Unlit/Transparent或调整Surface Type材质这块以我的经验内置渲染管线里最简单的做法是给角色或特效使用Unlit Transparent类型的Shader注意Queue是TransparentBlend是SrcAlpha OneMinusSrcAlphaZWrite关掉。URP工程里可以用Universal Render Pipeline/Unlit在Surface Type里选Transparent同样要确保材质球Alpha通道正常输出。顺便提一个容易被忽视的点后处理会破坏Alpha。Bloom、Depth of Field、Color Grading、Tonemapping这些效果在计算时会把背景的Alpha值搅乱导致角色边缘出现脏污或发光残留。录制透明序列帧时后处理Volume要么移除要么把Post Processing关掉再做后期再合成。4. RecorderTimeline完整实战从配置到输出的每一步现在进入实操环节按我常用的一套流程写照着做基本就能跑通透明序列帧输出。第一步整理录制场景。把不需要的背景物体、不该出现在画面里的UI、干扰光源全部隐藏。灯光建议保留一到两盏主光负责造型补光负责暗部细节。如果角色有自发光材质或特效先确认它们在透明Shader下不会变成黑色色块。第二步配置专用摄像机。创建一个CameraClear Flags设为Solid Color背景色的Alpha手动改成0。这里注意颜色本身是什么不重要因为Alpha已经是0但建议把RGB也设为纯黑这样即使某个环节出错至少预览时能看到明显的黑底提示自己哪里没调对。Unity的Camera组件里背景Alpha要手动在颜色选择器里拖记得确认。第三步搭建Timeline并预览。创建PlayableDirector和Timeline Asset把角色动画、摄像机动画、特效开关全部挂在时间轴上。此时先在Timeline窗口从头到尾拖一遍播放头确认没有跳帧、穿帮、异常渲染。预览时建议关掉GameView的显示让它保持干净。第四步配置Recorder。在Recorder窗口添加PNG Sequence录制器。关键参数按我常用的来参数项推荐值说明CaptureTargeted Camera指定专用摄像机远离GameView干扰Camera你新建的录制摄像机必须指定不能留默认Resolution1920x1080或按需求四类需求的分辨率建议见文末Frame Rate30fps或目标帧率与动画最终播放帧率强制一致Start Frame0起始帧End Frame动画总帧数-1比如1秒动画30fps就是0到29Output FormatPNG官方优先级最高的透明输出格式Output Path项目内或指定目录用$Takes做子目录很方便文件名通配符这里多说一句。Recorder支持类似$F帧号、$T时间、$Take批次这类占位符。我个人最常用的是hero_idle_$F这样的格式输出出来就是hero_idle_0000、hero_idle_0001顺序可预测后期合成时按序号拖入即可。第五步确认透明选项。PNG Sequence在Capture为Targeted Camera时会提供透明相关选项确认已勾选。输出格式选PNG的情况下透明通道是原生支持的不需要额外编码器。如果你用的是Movie Recorder只有ProRes 4444或WebMVP9这类格式支持AlphaH.264一律不支持透明通道这也是我推荐PNG序列的原因。第六步点击Start Recording。这里有个重要经验点下去之后就不要再碰编辑器了。Recorder工作时会接管GameView逐帧推进时间轴采样如果你在窗口上鼠标点来点去或者不小心弹出一个菜单这些UI可能被录进画面鼠标光标也可能会出现在序列帧里。点完Start去喝杯水回来就好。录制完成后打开输出目录检查。再次强调透明区域在资源管理器里显示为黑色是正常的用Photoshop或者AE打开看把白色背景图层隐藏掉确认透明范围正确、角色边缘没有脏边这批次就算成功了。这套流程跑通之后建议把Recorder的配置保存为Preset下次直接加载。如果项目需要多种分辨率或多种帧率就分别保存几个Preset切换到具体需求时一键换配置不用每次重新填参数。5. 输出后必做的三项检查Alpha边缘、分辨率匹配与序列完整性序列帧录出来不等于完事后面这三项检查我每次都会做而且基本都能查出点问题。第一项是Alpha边缘检查。把PNG序列导入Photoshop或AE关闭背景图层后放大到200%看角色边缘。正常的边缘应该是干净利落或者至少是自然的半透明度过渡。如果看到一圈白色或淡灰色描边说明材质输出的Alpha和RGB不匹配——这通常是没有关闭ZWrite导致的遮挡混合或未正确设置Blend。如果边缘有明显的锯齿多半是录制时开了抗锯齿抗锯齿会把边缘像素和背景混在一起在合成软件里反而变成半透明脏边。我录制透明序列帧时会把Quality Settings里的Anti Aliasing设为关抗锯齿放到后期合成阶段再做。第二项是分辨率与帧率匹配。分辨率取决于最终用途用途建议分辨率帧率视频素材宣传片/广告2K或4K24fps或30fps游戏内UI动画按UI控件实际大小30fps动画预览缩略图小图512x512即可15fps即可微信小游戏/真机按内存预算缩放30fps这里有一个反复踩坑的教训导出之前先问清视频组或UI同学的最终分辨率。如果视频最终是1080p你录制2K没问题但如果素材要放到4K工程里缩放1080p就不够用重录一遍耗时不说角色动作还未必能完全复刻。帧率同理视频组如果定的是24fps你按30fps录交付给后期就会慢速播放如果游戏内播放是30fps你按24fps录真机跑起来就会感觉卡顿。第三项是序列完整性校验。录了120帧中间如果缺一帧后期合成时画面会顿一下。一个人眼去数显然不现实我习惯用一个简单的Editor脚本来统计PNG数量并检查编号是否连续。思路是遍历文件夹里的PNG文件解析文件名中的帧号检查最大值、最小值和总数是否对得上。代码不复杂核心逻辑长这样using UnityEngine; using UnityEditor; using System.IO; public static class SequenceCheck { [MenuItem(Tools/Check PNG Sequence)] public static void CheckPngSequence() { string folder EditorUtility.OpenFolderPanel(选择序列帧目录, Application.dataPath, ); if (string.IsNullOrEmpty(folder)) return; string[] files Directory.GetFiles(folder, *.png, SearchOption.TopDirectoryOnly); if (files.Length 0) { Debug.LogError(目录下没有PNG文件); return; } int minFrame int.MaxValue; int maxFrame int.MinValue; foreach (string file in files) { string name Path.GetFileNameWithoutExtension(file); int index name.LastIndexOf(_); if (index 0 || index name.Length - 1) continue; if (int.TryParse(name.Substring(index 1), out int frame)) { minFrame Mathf.Min(minFrame, frame); maxFrame Mathf.Max(maxFrame, frame); } } int expected maxFrame - minFrame 1; Debug.Log($帧范围: {minFrame} - {maxFrame}); Debug.Log($实际数量: {files.Length}, 期望数量: {expected}); if (files.Length ! expected) { Debug.LogWarning(序列帧不完整可能中间缺帧); } } }这个小脚本并不复杂但在动辄几百帧的项目里能让人少盯屏幕多休息。还有一种可能导致的缺帧情况是录制过程中资源加载引起的丢帧遇到这种情况排查思路是先降低场景复杂度再检查Quality Settings最后考虑是否开启了垂直同步或Adaptive Performance这类帧率控制机制。6. 实战中绕不开的坑与优化阴影、包围盒、录制性能与平台适配最后这部分是我在实际项目里被坑过好多次之后总结出来的专门列出来讲。先讲阴影问题。很多人在透明序列帧录制时发现角色像贴纸一样浮在画面上没有体积感。原因是我们为了透明输出用了Unlit类Shader它不带光照计算角色自然没有明暗变化。如果画面里原本依赖实时阴影来体现角色和地面的接触换成透明输出后阴影全没了。我的做法是分两条路走。第一条路追求高质感画面用支持透明输出的带光照Shader内置管线可以用Transparent/Diffuse或自定义Lambert并单独设置一个Shadow Only的透明平面让角色阴影投上去。这样录出来的序列帧自带Alpha且角色有阴影后期合成时不需要额外做投影。代价是Shader选择更挑剔URP下需要写一点Shader Graph或自定义Shader。第二条路录制时完全不关心阴影靠后期合成软件在视频里补一个柔和的模糊阴影或者直接把角色素材放到合成层的单独一层让后期自己去处理投影。这是大多数游戏项目常见的做法因为实时渲染的硬阴影和后期视频的光影风格未必匹配交给后期处理反而更灵活。再讲包围盒与摄像机视野计算。录制动作幅度大的模型时如果摄像机尺寸靠人工估计很容易出现角色手或脚被裁切的问题而且往往录到一半才发现。我现在的做法是写一个Editor工具选中角色后自动遍历所有Renderer计算Renderer.bounds的总包围盒再根据摄像机的正交尺寸或FOV自动调整摄像机距离和位置。核心思路是这样using UnityEngine; using UnityEditor; public static class CameraFitHelper { [MenuItem(Tools/Fit Camera To Renderer Bounds)] public static void FitCameraToBounds() { Transform root Selection.activeTransform; if (root null) return; Renderer[] renderers root.GetComponentsInChildrenRenderer(); if (renderers.Length 0) return; Bounds bounds renderers[0].bounds; for (int i 1; i renderers.Length; i) { bounds.Encapsulate(renderers[i].bounds); } Camera cam Camera.main; if (cam null) return; if (cam.orthographic) { float maxSize Mathf.Max(bounds.extents.x, bounds.extents.y); cam.orthographicSize maxSize * 1.2f; Vector3 pos bounds.center; pos.z cam.transform.position.z; cam.transform.position pos; } else { float maxSize Mathf.Max(bounds.extents.x, bounds.extents.y, bounds.extents.z); float distance maxSize / Mathf.Sin(cam.fieldOfView * 0.5f * Mathf.Deg2Rad); Vector3 pos bounds.center - cam.transform.forward * distance; pos.y bounds.center.y; cam.transform.position pos; } Debug.Log($Bounds center {bounds.center}, size {bounds.size}); } }这段代码思路供参考选中角色后取所有Renderer的联合包围盒正交摄像机就调整Orthographic Size透视摄像机就调整距离。加上1.2倍余量给动作扩展留出空间。这样在批量导出多个动作时摄像机参数不用靠肉眼反复试。录制性能也是个常见痛点。Recorder逐帧采样很吃CPU/GPU如果场景复杂会出现两种情况一种是每帧渲染时间变长录制速度变慢另一种是性能抖动导致个别帧采样异常。我通常在录制前做一次Quality Settings调整抗锯齿关掉Soft Particles关掉Shadow Distance适当降低后处理全部关掉。录制是离线的目的是得到干净的画面不是在编辑器里实时跑出高帧率。还有后面接平台适配的问题。微信小游戏、小程序这类环境透明视频播放的兼容性一直很头疼iOS和安卓的VideoPlayer行为不一致有些安卓机播不了透明WebM有些播不了带Alpha的H.264。序列帧在这种环境里反而成了最优解运行时本质上只是图集切换跨端行为统一可控。代价是内存。一张1024x1024的RGBA PNG大概4MB30帧就是120MB这在移动端是不可接受的。所以序列帧在游戏内播放时一定要走图集和压缩把多张小图合并成一张Atlas记录每个格子的UV运行时用UV偏移做翻页或者用ETC2/ASTC压缩纹理内存能降好几倍。如果动画内容是平移、旋转、缩放这种简单运动甚至可以只烘焙关键帧运行时做插值帧数直接从30帧降到6到8帧。按照我的习惯规范化流程之后会做一套一键烘焙工具选中角色和一个动画Clip自动建Timeline、自动挂材质、自动调摄像机包围盒、自动出PNG最后自动合并图集并生成Asset。一开始搭这个工具花了两天之后所有序列帧输出需求都变成了点一个按钮的事。这套流程真正值得投入的就是把场景规范化、把材质方案定死、把Recorder配置存成Preset剩下的只是时间问题。录一次序列帧不难难的是每次都能稳定复现同样的结果。把工具拼齐后面不管谁来找你要序列帧你都能当天交付。
返回列表