本节摘要:Blackboard 是图与外界之间的参数接口:属性暴露后出现在材质面板上,改值不需要重新编译。本节把属性类型、模式、参考名三个概念讲透,并把 1.2 节的渐变图升级成"颜色、渐变速度、方向都可调"的参数化版本。
想象一个常见的排期场景:场景里有一百个能量水晶,美术要求它们用同一个着色器,但每颗的颜色深浅、呼吸快慢不同。如果颜色写死在图里,你就得做一百张图——显然不对。正确的做法是把"变化的量"做成 Blackboard 属性,图只有一张,材质有一百个,每个材质填自己的值。
这个"变化与不变的分界线"就是属性设计的核心判断:所有实例共用的逻辑留在图里,逐实例不同的数据做成属性。
Blackboard 加号下有一长串类型,日常真正高频使用的是下面这些。每种类型对应着色器里的一种数据结构,选对类型能避免后面连线的类型转换麻烦。
| 属性类型 | 用途 | 材质面板形态 | 注意点 |
|---|---|---|---|
| Color | 纯色、发光色 | 颜色选择器 | 默认带透明通道,注意 Alpha 值 |
| Vector1 | 标量参数 | 滑条或数字框 | 设 Min Max 后变滑条,调参手感最好 |
| Vector2 或 Vector4 | 坐标、偏移量 | 多字段输入 | UV 平铺偏移常用 Vector2 |
| Texture2D | 贴图 | 贴图槽 | 需配合采样节点使用 |
| Boolean | 开关 | 勾选框 | 常配合关键字做分支 |
| Gradient | 渐变 | 渐变编辑器 | 内部按关键帧生成纹理采样 |
点击画布上的属性节点(或 Blackboard 里的条目),检查器里出现关键字段。默认值(Default)是新材质的初始值;模式(Mode)对 Color 属性可选 HDR——勾上后颜色亮度可以超过一,配合泛光后处理能做出"过曝发光",第 5 章全息案例会用到;参考名(Reference)是脚本访问用的内部名,见下文。
暴露(Exposed)勾选框决定该属性是否出现在材质面板上。听起来"不暴露就没意义",其实不然:不暴露的属性会退化为编辑器内的常量(相当于图内默认值),用处是在你保留一个数值但同时想允许 C# 代码通过材质属性块在运行时覆盖它的场景。初学阶段建议全部保持暴露勾选,概念先简单化。
**参考名(Reference)**是脚本里用 material.SetFloat("参考名", 值) 访问时的字符串。Unity 自动生成的参考名带下划线前缀加哈希(形如 _Vector1_a1b2c),又长又不可读。只要这个图会被代码调用,就手动把参考名改成可读形式,比如 _DissolveAmount、_OutlineWidth——脚本对接时你会感谢现在的自己。

回到 1.2 节的渐变图,做四个改动。改动一:添加 Color 属性命名 TopColor,默认浅黄,拖进画布接到 Lerp 的 B 端;同法添加 BottomColor 接 A 端。改动二:添加 Vector1 属性命名 GradientSpeed,Min 设 0、Max 设 10,先不接线——下一章讲 Time 节点时让它派上用场。改动三:把 UV 拆出的 G 接 T 的路径保持不变,保存。改动四:在场景里复制三个立方体,给它们各自的材质把 TopColor 调成不同颜色——三个物体同一张图、三种外观,参数化的价值一目了然。
顺手做一个对照实验:把 GradientSpeed 属性的暴露勾选去掉,保存后看材质面板——滑条消失了,但属性节点还在画布上。这个状态就是"图内常量",适合那种"暂时写死、以后可能开放"的中间态参数。
给接手项目的程序留个底:属性暴露后,代码侧通过材质或属性块写入。下面这段脚本让物体的颜色在两个颜色间来回过渡(挂到任意物体上,把材质拖到字段里即可运行):
using UnityEngine; public class ColorPulse : MonoBehaviour { public Material targetMaterial; // 使用该图的材质 public Color colorA = Color.blue; // 一端的颜色 public Color colorB = Color.yellow; // 另一端的颜色 public float speed = 1f; // 过渡速度 void Update() { // 按参考名写属性,与 Blackboard 里的 Reference 字段一致 float t = Mathf.PingPong(Time.time * speed, 1f); targetMaterial.SetColor("_TopColor", Color.Lerp(colorA, colorB, t)); } }
跑起来后你在场景里会看到颜色随时间摆动——这就是"图定义逻辑、属性喂数据"的完整闭环。注意 SetColor 的第一个参数必须与参考名完全一致,大小写敏感;参考名没改过就用自动生成的长串,别凭感觉猜。
经验区间是三到八个。少于三个,效果往往缺乏可调性(比如只有颜色的渐变图,换个亮度需求就得改图);多于八个,材质面板变成考卷,使用者根本不知道哪个滑条管什么。超出的需求怎么办?把相关的参数合并:四个分离的颜色输入往往可以合并成"渐变两端加中点"三个;速度与幅度这类独立物理量保持独立,别为了凑数合并语义不同的参数。
Min 与 Max 的取值决定了调参手感。细节一:范围要覆盖"合理使用域"而不是"数学合法域"——波高滑条给 0 到 1,美术不会去拖 500,但 0 到 500 的滑条每次微调都像抽签。细节二:默认值放在常用区间而不是区间中点:溶解进度默认 0(未溶解)比默认 0.5(半溶解)符合直觉。两个细节合起来一句话:滑条是给人用的,先想清楚谁在拖、拖到哪。
常见做法是把某个强度属性的默认值设为 0 来"关闭"效果——运行时零成本,看似完美。陷阱在于:图里那段计算仍然每次执行(乘以零还是乘法),并且美术可能随手把滑条拉起来,触发你从未测试过的状态。如果这个效果"开与关"是明确的二元状态,7.3 节的关键字才是正解;如果只是"弱到看不见",属性归零才是对的。两者的分界线是:关掉后那段节点链还该不该存在。
属性做完后过一遍验收:每个属性有可读的名字与合理的范围;默认值让物体在新建材质时就表现正常;脚本要用的属性已改参考名;材质面板上逐个拖动,效果响应方向与数值方向一致(拉大波高应该更浪而不是更平)。最后一条看似废话,但方向接反的属性在交付后才发现,返工的尴尬远大于检查的三分钟。
参数已经可以调了,下一节我们把视线转向数据流的终点——主栈的块与端口,弄清 Alpha、Emission 这些端口分别通向渲染管线的什么机制。