A struct-like Graph value that carries a whole material's attribute set as one connection, written and
read member by member. (since 1.2.5)
Declared in
.dsm, .dsf — inside a Graph { … } body, an Outputs declaration, or a function Inputs / Outputs section
Kind
value type
Generates
UMaterialExpressionMakeMaterialAttributes (an empty set), UMaterialExpressionSetMaterialAttributes (written attributes, where the value is used), UMaterialExpressionBreakMaterialAttributes (member reads)
An empty set: one MakeMaterialAttributes node with every input unconnected. Unlike Texture2D and Substrate, a MaterialAttributes declaration does not require an initializer.
MaterialAttributes Attrs = {};
Identical to the bare declaration — an empty brace initializer is no initializer.
MaterialAttributes B = A;
B takes A's value. No node is created.
MaterialAttributes Attrs = F_Layer(uv);
Any expression whose value is a MaterialAttributes — a function call, a StaticSwitchParameter call.
[!WARNING]
In a Shader, an Outputs declaration creates the variable(since 2.0.0). Every Outputs
declaration is declared at the top of the material's body, and a MaterialAttributes one starts as
an empty set, so Attrs.BaseColor = Tint; works with no Graph declaration at all. A
MaterialAttributes Attrs; in the Graph names that same variable and adds nothing:
In a function block a MaterialAttributes output is the function's output: the attributes written
to it make its set, and reading one never written is
DSH4370.
[!NOTE]
MaterialAttributes B = A; is a value copy, not an alias. A later B.Roughness = r; changes B
only; A keeps its attributes.
The attribute table is the engine's (since 2.0.0): an attribute this engine does not have is
DSH5200. A member name is matched exactly first (name or
alias), then ignoring case, with the warning DSH5276. Aliases
are exact synonyms.
Member
Aliases
Components
BaseColor
—
3
Metallic
—
1
Specular
—
1
Roughness
—
1
Anisotropy
—
1
EmissiveColor
Emissive
3
Opacity
—
1
OpacityMask
—
1
Normal
—
3
Tangent
—
3
WorldPositionOffset
WPO
3
SubsurfaceColor
—
3
CustomData0
ClearCoat
1
CustomData1
ClearCoatRoughness
1
AmbientOcclusion
AO
1
Refraction
—
3
CustomizedUV0 … CustomizedUV7
—
2
PixelDepthOffset
PDO
1
Displacement
—
1
DiffuseColor
—
3
SpecularColor
—
3
SurfaceThickness
—
1
FrontMaterial(UE 5.4+)
—
a Substrate value
MaterialAttributes
Attributes
the whole set
The 1.x aliases CustomizedUVs0 … CustomizedUVs7 are not in the alias table (since 2.0.0);
write CustomizedUV0 … CustomizedUV7.
MaterialAttributes (alias Attributes) resolves as a member (since 2.0.0; 1.x rejected it): it
is the whole set, and it is what the binding Base.MaterialAttributes = Attrs; writes. To replace a
Graph variable's whole set, assign the variable itself: Attrs = Other;.
[!NOTE]
The engine fork macro MOON_ENGINE adds the members MoonEncodedAttribute0 through
MoonEncodedAttribute4. The pre-rename spelling MooaEncodedAttribute0 …
MooaEncodedAttribute4 is accepted as an alias, so decompiled MooaToon functions still parse. They
do not exist in a stock UE 5.3–5.8 build.
A read of an attribute the body has already written in this value is that written value; no node is
made. Any other read comes from one UMaterialExpressionBreakMaterialAttributes per value, shared by
all of that value's reads (since 2.0.0; 1.x made one Break node per read).
[!WARNING]
A read that has to go through the Break node needs the engine's Break node to publish the
attribute; one it does not publish is DSH8216. This depends
on the engine build. A value with nothing to read from — a function's MaterialAttributes output
before anything was written to it — is DSH4370.
The read result is a plain numeric value with the member's component count, so it may be swizzled:
Attrs.BaseColor.r is an attribute read followed by a channel selection.
A member write records the value for that attribute; a later write of the same attribute replaces
it. Nodes are made where the value is used — passed to a function or a pin, assigned to an
output, bound to the material: one UMaterialExpressionSetMaterialAttributes on top of the value's
set, with one pin per attribute written so far (since 2.0.0; 1.x chained one Set node per write).
A value with no set underneath — a function's output — becomes one MakeMaterialAttributes with the
written pins instead.
Rule
Code when it fails
The target is name.member; a member of a member is not a target
on a number the member is read as a swizzle, DSH4230; on a texture DSH4206; on a Substrate value DSH4207
The member name must resolve
DSH5200
The value must fit the member's type
DSH4228; a wider vector gives its leading components with the info DSH5289
Coercion follows the normal rules: a scalar spreads, a wider value is cut to its leading components
(DSH5289), and a float2 assigned to a float3 member is an error. See
Conversions.
[!NOTE]
Attrs.BaseColor.r = 1.0; is DSH2206. There is no per-channel attribute write in a 1.x Graph;
build the full value first.
A declared name is one identifier, so MaterialAttributes A.B = x; is
DSH2154(since 2.0.0).
Attrs.BaseColor = {1.0, 0.35, 0.1}; is DSH2162(since 2.0.0): a brace list is read only as a declaration's initializer. Write the constructor,
Attrs.BaseColor = float3(1.0, 0.35, 0.1);.
In a Shader, declares the variable Attrs, starting as an empty set (see above).
Base.MaterialAttributes = Attrs;
Binds the value to the material and turns Use Material Attributes on.
ShaderFunction / ShaderLayer / ShaderLayerBlend / VirtualFunction inputs and outputs
Accepted. The argument must already be a MaterialAttributes value; nothing is converted (DSH4226 for an input, DSH4218 for an output variable of another type).
GraphFunction result type
Accepted — MaterialAttributes is one of the recognized result-type tokens.
if / else
The arms' attributes are merged one by one: one conditional node per attribute the arms disagree on. Assigning a different whole set in the two arms is DSH4375 — see if / else.
StaticSwitchParameter call branches
Accepted when both branches are attribute values.
Constructor argument
Rejected — DSH4226.
Arithmetic operand
Rejected — DSH4226.
Binding Base.MaterialAttributes is documented in full in
Output bindings.
Substrate is a separate value type, not an attribute set, and requires UE 5.4 or newer. The
two never convert into each other.
Situation
Behaviour
Substrate value assigned to a MaterialAttributes target, or the reverse
DSH4228
Substrate value assigned to any numeric target, including an attribute member
DSH4228
Substrate value with .member
DSH4207, except on a Substrate value still being built — see Substrate builtins
Substrate value as an if branch value
a StaticSwitch under a static condition, otherwise Substrate.Select (UE 5.6+) or DSH4378 — see if / else
Attrs.FrontMaterial
The member resolves on UE 5.4+ and is typed Substrate(since 2.0.0; 1.x typed it as one number). The usual route for a Substrate surface is still the Base.FrontMaterial output binding.
Base.MaterialAttributes and Base.FrontMaterial in one Shader
Not refused (since 2.0.0). Both are wired, and Use Material Attributes, which the first one turns on, makes the material read the attribute set and not its individual pins.