news 2026/10/16 9:56:17

PS到Unity自动化工具链:欧美卡通舞台2D场景搭建实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PS到Unity自动化工具链:欧美卡通舞台2D场景搭建实战

上手欧美卡通风格的舞台场景,最难的不是把画面画好看,而是让美术在PS里画的东西,原封不动、高效地变成Unity里的完整舞台。我在某项目里就吃过这个亏:舞台帷幕、装饰摆件、地面光斑、背景大屏,加起来几十张贴图,美术手动导出一次,程序手动拖进Unity一次,再手动调一遍导入参数,结果图没对齐、参差不齐、命名混乱,返工改到深夜。这篇是我整理的 PS 到 Unity UI/2D 自动化工具链第一篇,核心是把欧美卡通舞台的视觉规范定下来,再让“PS 导出”和“Unity 导入”这两个环节尽量全自动。项目用的是最常规的 Unity 2019 LTS 加 2D 工作流,适合独立开发者、小团队,也适合被资源导入折磨到想写脚本的美术同学参考。

1. 一次返工逼出来的自动化思路:为什么先做工具链再搭舞台

1.1 手动流程到底有多痛

先说一个很典型的半天工作流。美术在 PS 里画好一张舞台背景,导出 PNG,命名叫“最终版2_改”,拖进 Unity,发现透明通道发灰,手动把 Texture Type 改成 Sprite、把 Compression 改成无压缩,再拖进场景调 Sorting Layer。搞定。下一张装饰摆件,再来一遍。十几张图,至少大半天没了。

更要命的是,Unity 的导入参数很多时候不是画完才设置,而是每次改动贴图后都要确认一遍。如果你在 PS 里把帷幕颜色从红色改成了酒红色,导出文件覆盖之后,Unity 还得重新检查参数。如果某张图忘了关 mipmap,移动端上就会平白多出几十MB内存,这问题在项目后期才爆出来,排查成本极高。

我那时候总结了一句话:在2D美术资源管线的场景里,手动操作越少,踩的坑越少。工具链的本质不是“做一个编辑器窗口”,而是把“人肉重复劳动”替换成“脚本按规则执行”。

1.2 工具链带来的三个变化

这套工具链做完之后,最直观的三个变化是:第一,命名规范了,美术不需要记忆复杂规则,直接在图层命名里打上标签,导出脚本自动分类;第二,Unity 导入参数不再靠肉眼检查,AssetPostprocessor 会在贴图导入时按目录自动配置;第三,PS 到 Unity 中间多了一层 JSON 元数据,每张贴图的尺寸、偏移、排序层级都在 JSON 里,场景搭建阶段可以直接读取,减少大量重复拼图。

很多刚开始做自动化的人会担心:写脚本的时间比手动导图的时间还长,值得吗?我的回答是,只要你的项目里同一个流程要重复三次以上,就值得。我这边因为舞台场景会频繁换版本,每隔两三周就要重新出一套背景和装饰,脚本初版写了两天,但后面每次改版都省下半天到一天,回本很快。

1.3 第一篇的边界:这次做到哪一步,下一步做什么

既然是第一篇,我不打算一次把所有功能都铺开。这一篇先把底子打好,让一张图片从 PS 到 Unity 的路径自动跑通,并且能搭出一个基础舞台场景。具体包括:欧美卡通舞台的视觉拆解和美术规范、PS 导出脚本的核心设计、Unity 侧自动导入参数的处理、Sprite 图集构建思路、舞台排布和灯光氛围的基础做法,以及我踩过的一堆坑。

程序化摆放、舞台元素随机组合、音乐律动同步、换装系统这些,属于后续第二篇、第三篇的内容,这篇不展开。如果你只想看某一段,可以直接跳到对应章节,但我建议顺序读一遍,因为很多坑是跨环节的,比如 PS 里导出的颜色和 Unity 里看到的对不上,这类问题只在整条链路都过一遍之后才会暴露。

2. 欧美卡通舞台的视觉拆解:剪影、配色与分层标准

2.1 “卡通味”从哪来:剪影、轮廓线与高饱和配色

很多同学以为欧美卡通风格就等于“描个黑边”,其实不对。你看那些经典的欧美卡通舞台场景,第一眼抓人的其实是剪影:大色块、大比例、大弧线。帷幕的波浪、舞台拱门的圆角、装饰物的夸张尺寸,都在剪影阶段就定了调。

所以我在美术规范里第一件事不是定描边粗细,而是定剪影语言。比如舞台正面拱门,要求是一条连贯的大弧线,不要碎成一堆小装饰;装饰树木或花盆,要求比正常比例大 1.2 到 1.5 倍,让视觉重心更稳。这个阶段可以用纯色块在 PS 里先摆一版,不需要细节,只需要确认整体轮廓的辨识度。

然后是轮廓线。欧美卡通通常有明确的深色描边,我的经验是描边宽度不统一,是手绘转 Unity 时“最显廉价”的原因。我在规范里直接规定:主体轮廓线 6px(按 2048 尺寸基准),内部结构线 3px,最细的装饰线不低于 2px。这个数值不是固定的,但你必须在项目里定一个统一基准,Unity 侧的显示才稳定。

配色上,欧美卡通风格的特点是饱和度偏高、明暗对比强烈。通常我会让美术在 PS 里用一个受限的色板,比如舞台帷幕红色系只允许 4 个色阶,避免出现太多灰蒙蒙的中间调。写实风格需要大量中间过渡色,但卡通舞台恰恰要敢用大平涂,色阶分明才有“卡通感”。

2.2 舞台场景的通用分层:背景层、装饰层、角色层与前景层

舞台场景从纵深上天然分几层:最底下的背景墙、中间的舞台地板和拱门、再往前是道具装饰、角色站位区,最前是帷幕和光晕等前景元素。我在 PS 的图层结构里也按这个顺序来建组,导出脚本才能直接映射到 Unity 的 SortingLayer。

这里有个很容易犯的错误:美术喜欢在 PS 里把所有图层都画在同一个画布上,背景和前景叠在一起导出成一张大图。这样做虽然省事,但在 Unity 里想要做遮挡、做动画、做置换的时候就很麻烦。我的建议是,相同纵深关系的元素合成一张图,不同层级的元素必须拆开导出。比如“背景墙+地面”可以合成一张,但“前景帷幕”必须单独导出。

分层还有一个好处:处理灯光和后期时,你可以只对前景层做模糊,对背景层做不同色调,视觉层次一下子就能拉开。后文工具链里的 JSON 清单,也是基于这套分层来记录每张贴图应该落在哪个排序层级。

2.3 色彩空间在 2D 项目里的决策:Gamma 还是 Linear

这个看起来像技术参数,但直接影响美术在 PS 里调好的颜色会不会在 Unity 里“变灰”。 我在项目里用的是Gamma 色彩空间。原因很简单:2D 手绘贴图本来就是在 sRGB 下绘制和查看的,纹理文件里的颜色值就是最终显示的颜色。开了 Linear 之后,贴图默认按 sRGB 解码再做光照计算,如果材质和渲染管线的补偿没做好,颜色会整体变暗或偏色。

当然,用 URP 或者 HDRP 做 3D 风格化渲染时,Linear 是通用选择,但纯 2D 卡通舞台项目,我的经验是别折腾。这篇文章里的工具链默认“纹理保持 sRGB,项目色彩空间用 Gamma”,后面踩坑章节还会讲一次我试图改 Linear 之后的教训。

3. 工具链整体架构:PS导出、中间规整、Unity导入三段式

3.1 完整链路拆分:从 PS 到 Unity 要经过哪几步

整套流程我分成三段。第一段是 PS 侧的 ExtendScript 脚本,它负责读取一个约定好的 PSD 文档,按照图层组和图层命名,把目标元素导出成单独的 PNG,并且在导出完成后生成一份 JSON 清单。第二段是中间规整,也就是一个命令行或手动执行的小工具,用来检查 PNG 文件和 JSON 清单是否完整,文件命名是否规范,这个步骤可以放在 CI 里,也可以不放,我最早是手动双击运行。

第三段是 Unity 侧的脚本。这里分成两部分:一部分是 AssetPostprocessor,在贴图导入时自动设置参数;另一部分是编辑器脚本,在导入完成后读取同目录下的 JSON 清单,把 Sprite 的元数据写到 ScriptableObject 里,供场景搭建阶段使用。

这根链条最核心的思路是:让文件系统成为美术和程序之间的唯一接口。美术把 PSD 按规范建好,脚本负责导出;程序不关心美术在 PS 里怎么组织图层,只关心最终 PNG 和 JSON 的字段是否合规。

3.2 为什么用 JSON 清单,而不是只靠文件名猜参数

有人可能觉得,PNG 文件名带个 _Back 后缀,Unity 那边按后缀解析不就行了?为什么还要一份 JSON?

我的理由是,文件名可以做简单的分类标记,但承载不了完整信息。比如一张装饰树的贴图,它除了是装饰层之外,还要记录它在画布中的原始位置、它是否需要开启 alpha、它的 pivot 应该放在哪里、它属于哪一组可交互元素。这些信息塞进文件名会乱七八糟,可读性极差。

JSON 清单就干净多了。PS 脚本导出时,按元素把它的 bounds(原始画布内的矩形位置)、图层的可见性、所属分组名称、导出的 PNG 文件名、建议的 pivot 位置都记录下来。Unity 侧的导入器读取这份 JSON 后,可以为每个 Sprite 自动创建导入配置。以后再想加字段,比如“这个元素参与律动动画”“这个元素是聚光灯”,直接在脚本和 JSON 结构里加,不需要改 Unity 场景里的任意一个组件。

3.3 命名规范与目录结构:自动化工具链的地基

没有命名规范,脚本写得再漂亮也白搭。我最终定的规则是这样的:

资源类型目录前缀命名示例说明
背景层BGStage_Back_MainHall_01通常指背景墙+地板
舞台结构FRAMEFrame_Arch_01拱门、立柱、舞台边缘
装饰道具PROPProp_Plant_03可拆分的装饰物件
前景层FGFg_Curtain_Left_01帷幕、挂帘、光晕
灯光特效FXFx_Spotlight_Soft_01光斑、聚光灯贴图

所有 PNG 统一放Assets/AutoImported/下的子目录,比如Assets/AutoImported/BG/、Assets/AutoImported/FX/。Unity 侧的导入脚本只监听这个目录,原生的项目美术资源目录不受影响。

目录结构和命名规范是两件事,但必须一起定。刚开始做自动化的人常常只定命名,忘了定目录,结果脚本到处监听,项目层级一乱,后续所有规则都失效。我的建议是:先定目录,再定命名,最后才是脚本逻辑。

4. 在PS里写自动导出脚本:图层约定与批量出图

4.1 前端约定:图层组怎么建才能被脚本识别

PS 导出脚本的第一步,其实就是“美术怎么建图层组”。我在项目里约定的模板是这样的:PSD 根目录下必须有一个顶层组叫StageRoot,里面按BG、FRAME、PROP、FG、FX五个分组再建子组。每个需要单独导出的元素,在子组里单独占一个图层或一个图层组。

为了让脚本能识别“哪些图层要导出、哪些不用”,我建议每个导出元素的名字里带一个标记,比如[out]前缀或_out后缀。只有带标记的图层才会进入导出列表。这样做的好处是:美术可以放参考图层、草稿图层、色板图层在同一个 PSD 里,只要不写_out,就不会污染导出结果。

同时,所有需要导出的小组,PS 里默认必须是独立对象,不要和别的元素共用蒙版或混合模式,不然脚本很难稳定切图。这个环节没有捷径,必须在项目一开始就给美术讲清楚,否则后期靠脚本去猜,全是在补坑。

4.2 ExtendScript 脚本的核心逻辑

其实 PS 的 ExtendScript 就是 JavaScript 的变种,只要能遍历图层组、复制文档、隐藏多余图层、读取 bounds、保存 PNG,这个脚本就能成立。我的核心代码大概长这样:

// PS导出脚本核心逻辑(简化版) var doc = app.activeDocument; var rootGroup = null; for (var i = 0; i < doc.layerSets.length; i++) { if (doc.layerSets[i].name === "StageRoot") { rootGroup = doc.layerSets[i]; break; } } if (!rootGroup) { alert("未找到 StageRoot 组,请检查PSD结构"); } var exportDir = "D:/Projects/AutoExport/"; var manifest = []; var groupList = rootGroup.layerSets; function isExportableLayer(layer) { return layer.name.indexOf("_out") > -1; } function hideAllLayers() { for (var i = 0; i < doc.layers.length; i++) { doc.layers[i].visible = false; } } function exportLayerGroup(layerGroup) { var exportName = layerGroup.name.replace("_out", ""); var exportFile = new File(exportDir + exportName + ".png"); // 复制文档,避免动到原始PSD var tempDoc = doc.duplicate("temp", true); hideAllLayers(); // 在临时文档中定位同名图层组,只让它可见 var tempRoot = tempDoc.layerSets.getByName("StageRoot"); var targetGroup = tempRoot.layerSets.getByName(layerGroup.name); targetGroup.visible = true; // 获取 bounds,记录到 JSON var bounds = targetGroup.bounds; manifest.push({ name: exportName, x: bounds[0].value, y: bounds[1].value, width: bounds[2].value - bounds[0].value, height: bounds[3].value - bounds[1].value }); // 保存为PNG var pngOptions = new PNGSaveOptions(); pngOptions.compression = 6; tempDoc.saveAs(exportFile, pngOptions, true, Extension.LOWERCASE); tempDoc.close(SaveOptions.DONOTSAVECHANGES); } for (var g = 0; g < groupList.length; g++) { exportLayerGroup(groupList[g]); } // 最后把 manifest 写成 JSON 文件 var jsonFile = new File(exportDir + "manifest.json"); jsonFile.open("w"); jsonFile.write(JSON.stringify(manifest)); jsonFile.close();

这段代码是思路演示,真正跑起来还需要处理 PS 的坐标单位和众多 API 细节,但核心逻辑就是这样。最关键的技巧是:导出时不要直接保存原文档,而是复制一份临时文档,只把目标图层设为可见后再保存。这样原 PSD 的图层可见性状态永远不会被脚本破坏。

4.3 一次真实导出的输出示例

按上面的脚本逻辑,假如我的舞台项目里有这几个元素:

  • Stage_Back_MainHall_out
  • Frame_Arch_Left_out
  • Prop_Plant_03_out
  • Fg_Curtain_Left_out

导出完成后,AutoExport目录下会有四个 PNG,同时manifest.json长这样:

[ { "name": "Stage_Back_MainHall", "x": 0, "y": 0, "width": 2048, "height": 1400 }, { "name": "Frame_Arch_Left", "x": 120, "y": 300, "width": 320, "height": 760 }, { "name": "Prop_Plant_03", "x": 800, "y": 900, "width": 240, "height": 380 } ]

Unity 侧导入器拿到这份清单后,就能知道每个 Sprite 在舞台画布中的原始位置、尺寸边界。后面做舞台摆位时,甚至可以在脚本里按坐标自动摆放,不需要人肉对齐。

5. Unity侧自动导入管线:AssetPostprocessor与图集构建

5.1 自动识别目录并按类型配置导入参数

Unity 里每一个资源导入时都会走AssetPostprocessor,这是做自动化管线最常用的扩展点。我写了一个AutoTextureImporter,监听Assets/AutoImported/目录下的所有贴图,只要文件名以.png结尾,就自动把导入参数设好:

public class AutoTextureImporter : AssetPostprocessor { private void OnPreprocessTexture() { string lowerPath = assetPath.ToLower(); if (!lowerPath.StartsWith("assets/autoimported/")) { return; } TextureImporter importer = (TextureImporter)assetImporter; importer.textureType = TextureImporterType.Sprite; importer.spritePixelsPerUnit = 100; importer.alphaIsTransparency = true; importer.mipmapEnabled = false; importer.sRGBTexture = true; importer.filterMode = FilterMode.Bilinear; importer.textureCompression = TextureImporterCompression.Uncompressed; importer.spriteImportMode = SpriteImportMode.Single; } }

这个配置有几个细节值得展开说。第一,2D 项目里 mipmap 必须默认关掉,否则 UI 或 Sprite 在缩小时会有不自然的颜色过渡,还会增加内存。第二,spritePixelsPerUnit定为 100 是 Unity 默认值,如果团队有不同想法,最好从第一天就统一。第三,alphaIsTransparency开启后,Texture 边缘的透明度处理会友好很多,但要注意它跟资源压缩方式有关,某些压缩格式可能会忽略这个标记。

如果你有特殊需求,比如有些贴图不需要像素完美,可以用文件名加_noAlpha后缀,在脚本里做分支判断。文件命名规范在这里和导入脚本形成了闭环。

5.2 Sprite图集构建:自动放进一个图集还是手动分组

图集这个东西,小的项目可以拖后做,但舞台场景这种资源量,图集最好一开始就规划。我用的方案是:PS 导出后的 PNG 先按目录自动导入,然后由编辑器脚本分批创建SpriteAtlas,一个目录对应一个图集,比如Atlas_BG.spriteatlas管所有背景,Atlas_Props.spriteatlas管所有装饰。

用代码创建图集不复杂,大致思路是:在OnPostprocessAllAssets里检查新增资源是否落到了Assets/AutoImported/下,然后找到对应的图集,把新导入的 Sprite 塞进去。

private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { foreach (string assetPath in importedAssets) { if (!assetPath.Contains("/AutoImported/")) continue; string atlasPath = GetAtlasPathForAsset(assetPath); SpriteAtlasAsset atl = AssetDatabase.LoadAssetAtPath<SpriteAtlasAsset>(atlasPath); if (atl == null) continue; Object[] objects = new Object[] { AssetDatabase.LoadAssetAtPath<Sprite>(assetPath) }; atl.Add(objects); } }

这个方案的好处是资源一进工程就自动入图集,美术不需要手动拖拽。坏处是图集管理对目录结构很敏感,如果你把资源放错目录,图集就会缺失。所以一定要把目录规范做成团队默认共识。

5.3 元数据配置文件:让Unity场景知道“这张贴图该摆哪”

PNG 和 JSON 都导入之后,还差一步:如何让场景搭建时知道每张 Sprite 的原始画布位置?这个信息我存在 ScriptableObject 里,名字就叫StageElementMeta。

[CreateAssetMenu(fileName = "StageElementMeta", menuName = "Custom/StageElementMeta")] public class StageElementMeta : ScriptableObject { public string elementName; public string elementGroup; public Vector2 canvasPosition; public Vector2 canvasSize; }

Unity 侧的导入器读 JSON 后,为每个元素创建一个对应的 StageElementMeta 资源,和 PNG 放在同一个目录下。后续写场景搭建编辑器时,直接读这些 meta,按 canvasPosition 和画布基准点,把 SpriteRenderer 摆到对应世界坐标。这一步做完,整条工具链才真正闭环。

6. 搭建舞台场景:排序、灯光与后期氛围

6.1 搭建的第一步:先把灰盒摆出来再细化

很多人搭舞台场景直接往场景里拖贴图,结果层次乱了再慢慢调。我习惯先做一版“灰盒”:用纯色或最简单的占位方块,按舞台的纵深关系摆出背景墙、拱门、道具、前景的位置,确认大小比例、遮挡关系、镜头取景都没问题,再换成正式贴图。

灰盒阶段特别适合验证一件事:角色站在舞台的哪个区域不会被前景遮挡。欧美卡通舞台的视觉重心通常偏中下方,角色站位的中心点大概在舞台中偏左或中偏右,具体要看设计稿。如果灰盒阶段发现前景帷幕挡住了角色站位区,直接调灰盒位置就行,成本几乎为零。

6.2 SortingLayer排序规划:一张表解决场景混乱

Unity 的 2D 渲染排序由 SortingLayer 和 SortingOrder 两个参数决定。同一层级内,SortingOrder 越大越靠前。我的舞台项目排序表如下:

SortingLayer典型元素默认 SortingOrder
BG背景墙、地板0
FRAME拱门、立柱100
PROP装饰摆件、花盆200
CHARACTER角色站位300
FG前景帷幕、装饰挂链400
FX光斑、聚光灯特效500

这张表的实质是:把美术分层直接映射成渲染排序。PS 里怎么分层,Unity 里就怎么排。工具链里的 JSON 清单也写了每个元素所属的 group,Unity 导入器可以直接按 group 设置好 SortingLayer,甚至不需要人工干预。

6.3 卡通舞台的灯光怎么做:2D光照与贴图模拟两手抓

欧美卡通舞台通常都有明显的聚光灯效果,让人一眼看出“这是舞台”。实现方案有两种:一种是用 URP 的 2D Renderer 加 2D Light,另一种是直接用光斑贴图配合 Additive 混合模式。

我的建议是,如果项目只是 2D 舞台,不打算做复杂的动态光影,贴图模拟方案更稳。做法很简单:在 PS 里画一张中心亮、边缘柔和的圆形光斑贴图,导出为Fx_Spotlight_Soft_01.png,放到 FX 层,用 Additive Shader 或材质混合模式叠加在舞台上。因为不需要光照计算,这套方案在任何渲染管线都能跑。

如果你想用 URP 的 2D Light,也可以。给光源设置Sprite Light类型,把光斑贴图当光源的 Sprite,它就能按 Sprite 形状照亮场景。这个方案的好处是光斑可以被角色遮挡,形成真实的影子效果。但要注意 URP 2D Light 需要对场景物体添加Shadow Caster 2D组件,否则影子的形状不可控。

6.4 后期效果和色彩统一:让舞台“活”起来

搭完所有贴图后,灯光和后期才是让舞台从“死板”到“生动”的关键。我用的后期配置是:Bloom(泛光)、Color Adjustments(色彩微调)和 Vignette(暗角)。Bloom 对舞台这种高饱和卡通场景特别有效,可以让光斑和装饰上的亮色边缘有一点发光感,瞬间有演出氛围。

Color Adjustments 里,我会把饱和度和对比度都稍微调高,让颜色更有“卡通感”。这里注意,如果你用的是 Gamma 色彩空间,后期参数的调整幅度要保守一些,不然容易过曝。Vignette 则是把画布四周压暗一点点,让观众的视线集中在舞台中央角色身上。这三个参数够用,不需要堆一大堆 Post Process。

7. 实测踩坑:透明边缘、渲染排序与颜色失真

7.1 透明贴图边缘发灰:看起来像一圈白边

把 PS 导出的透明 PNG 放进 Unity,最常遇到的情况是:本来边缘渐变的透明区域,出现了一圈灰色或白边。这个问题在浅色背景上尤其明显。

根本原因是,PS 里透明像素的颜色通道可能不是纯黑,而是留下了抗锯齿的中间色。Unity 在按 alpha 混合时,如果颜色通道数值偏高,透过半透明像素看到的背景就会偏亮或偏灰。

解决办法有两个。第一个是在 PS 导出时清理边缘:使用“图层样式-去边”或“Matting”功能,让透明边缘的颜色值统一收敛。第二个是在 Unity 导入参数里把alphaIsTransparency打开,让纹理在导入时做一次 alpha 与颜色通道的补偿。如果你的材质是自定义 Shader,也可以加一句:

col.rgb /= max(col.a, 0.001);

把颜色通道除以 alpha,再做混合。这个操作能有效消除透明边缘发灰,但会影响非透明区域的亮度,用之前要测试一下。

7.2 半透明物体排序错乱:前景帷幕透底

舞台场景里有大量半透明元素,比如帷幕、光斑、装饰纱幔。排排序时最容易出的问题是:前景的半透明帷幕,被后面不透明的装饰物体挡住了,或者两者穿插显示,看起来像透明层叠错了。

这个问题说起来简单,排查起来最容易让人抓狂。Unity 的 SpriteRenderer 渲染排序,同一 SortingLayer 内按 SortingOrder,但不同 SortingLayer 之间先按 Layer 排序。如果你把帷幕放到了 FX 层,但实际它的语义是前景,那么它的渲染顺序就会被 FX 层一起带到最后,导致后面的装饰物体盖过帷幕。

我踩坑之后做的事,是把所有元素按“语义”而不是按“美术效果”来分排序层。帷幕属于前景,就必须在 FG 层,哪怕它的视觉上像特效。另外,半透明材质最好统一用同一渲染队列,我一般设到Transparent队列,避免某些元素跑到不透明队列里,被深度缓冲卡住。

7.3 颜色空间不一致导致色差:PS里好看,进Unity发暗

一次项目里,美术在 PS 里把光斑调成暖黄色,导进 Unity 后发现整体发暗、偏棕,怎么调色都不对。排查了半天,最后发现是项目色彩空间被设置成了 Linear。这个项目虽然是 2D 的,但当时有人为了接入某个 3D 特性改了设置,忘了改回来。

在 Linear 空间下,纹理默认按 sRGB 参与光照计算,再做 gamma 校正。SpriteRenderer 默认的材质如果没有做对应处理,颜色就会比 PS 里暗一截。我们的舞台场景没有 3D 光照需求,所以最终把 Player Settings 里的 Color Space 改回了 Gamma,颜色立刻和 PS 里一致了。

如果你必须用 Linear,那么请在材质 Shader 里手动对贴图做sRGB采样:

half4 texColor = tex2D(_MainTex, uv); #if defined(UNITY_COLORSPACE_LINEAR) texColor.rgb = LinearToGammaSpace(texColor.rgb); #endif

这样能让 Sprite 在 Linear 管线里也还原出 PS 里编辑的原始颜色。但说实话,纯 2D 项目没这个必要,别折腾。

跌跌撞撞走到这里,我最深的体会是:这套工具链真正值钱的不是那些脚本代码,而是项目里定下的“规范和边界”。美术知道怎么建图层组,程序知道资源一进目录就会被自动处理,策划知道改一版背景只需要重新出图再覆盖,整个团队不用在某个人脑袋里找流程。做全自动化工具链,很多时候是在做“团队之间如何沟通”这件事,脚本只是把共识固化的工具。下一步我准备在这个基础上做程序化舞台摆位,把最后一步搭场景也变成半自动操作,等实践一轮再写第二篇。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 9:56:14

计算机网络核心知识全解析:从分层模型到TCP/IP与网络排障实战

计算机网络是计算机相关专业里一门绕不开的核心课&#xff0c;也是一门“看着简单、学起来容易飘”的课。很多人捧着教材从第一章看到最后一章&#xff0c;协议背了不少&#xff0c;但一问到“两台电脑之间发一个网页请求&#xff0c;中间到底发生了什么”就卡壳&#xff1b;或…

作者头像 李华
网站建设 2026/10/16 9:56:14

博途PID仿真程序:离线整定与实战避坑指南

简介&#xff1a;这份资源是面向工业自动化初学者与PLC工程师的博途PID离线仿真实践包&#xff0c;围绕西门子TIA Portal平台&#xff0c;帮助读者在不连接实际硬件的情况下理解比例、积分、微分控制器的参数配置与系统响应。压缩包共40个文件&#xff0c;约680KB&#xff0c;以…

作者头像 李华
网站建设 2026/10/16 9:55:10

数智化企业网络容灾实战:从RPO/RTO设计到演练落地

这两年做企业网络架构&#xff0c;绕不开一个词&#xff1a;数智化。传统企业业务正在被数字化和智能化重构&#xff0c;产线系统、供应链调度、客服质检、风控决策全部搬到了线上&#xff0c;数据一中断&#xff0c;业务就是真金白银的损失。我自己的感受很直接&#xff1a;数…

作者头像 李华
网站建设 2026/10/16 9:53:32

PyTorch词向量模型实战:CBOW负采样与近义词检索

简介&#xff1a;基于PyTorch实现的词向量模型&#xff0c;是一套面向自然语言处理初学者与开发者的教学型代码包&#xff0c;帮助理解词向量&#xff08;Word Embedding&#xff09;如何将词汇映射为连续向量&#xff0c;并捕捉语义与语法关系&#xff0c;覆盖Word2Vec中CBOW与…

作者头像 李华
网站建设 2026/10/16 9:52:42

Windows 11彻底卸载Clawdbot:残留、注册表与自启动项清理指南

作为 Windows 11 用户&#xff0c;你有没有遇到过这种情况&#xff1a;一个叫 Clawdbot 的软件明明在"设置-应用"里点了卸载&#xff0c;任务管理器里却还能看到它的后台进程&#xff0c;甚至重启后又出现在启动项里。我一开始也以为是我没卸载干净&#xff0c;后来才…

作者头像 李华
网站建设 2026/10/16 9:52:34

PLC与传感器无线监控方案:从DTU到边缘网关的实现指南

搞自动化的人&#xff0c;早晚都会碰上一件事&#xff1a;现场 PLC 和传感器跑得好好的&#xff0c;领导或客户突然问一句——“能不能让我在手机上随时看到数据&#xff1f;”而且这句话通常还带着“尽快”两个字。PLC 传感器对接手机 APP 实现无线监控&#xff0c;本质上已经…

作者头像 李华