Value types
Every property value in a project file is plain JSON. RoFlux looks at what type the property really is, and turns your JSON into that type for you. This page shows how to write each one.
You never write Color3.new or Enum.Material.Neon. You write [255, 0, 0] or "Neon", and RoFlux works out the rest from the property it is going into.
The one rule to remember
Inside a declaration, the shape of a value decides what it is.
- An object
{ }is a child instance. - Anything else is a property. That means a number, text,
trueorfalse, or an array[ ].
So this does not do what it looks like:
"Floor": {
"$ClassName": "Part",
"Size": { "x": 4, "y": 1, "z": 4 } -- makes a child Folder called Size
}
RoFlux sees an object and builds a child instance named Size. The part keeps its default size. Write it as an array instead, which is always a property:
"Size": [4, 1, 4]
If you really want the object form, put it inside $Properties. Everything in there is a property, whatever its shape:
"$Properties": {
"Size": { "x": 4, "y": 1, "z": 4 }
}
Every type on this page has an array form. Arrays work everywhere: in the shorthand, in $Properties, when syncing, and when building a place file. The object forms only exist for when you want the names spelled out.
Quick reference
| Type | Write it as | Example | Same as |
|---|---|---|---|
| number | a number | "Transparency": 0.5 | |
| string | text | "Text": "Play" | |
| boolean | true or false | "Anchored": true | |
| Enum | the item name | "Material": "Neon" | Enum.Material.Neon |
| Color3 | [r, g, b] | "Color": [255, 200, 40] | Color3.fromRGB(255, 200, 40) |
| BrickColor | the name | "BrickColor": "Bright red" | BrickColor.new("Bright red") |
| Vector3 | [x, y, z] | "Size": [4, 1, 2] | Vector3.new(4, 1, 2) |
| Vector2 | [x, y] | "AnchorPoint": [0.5, 0.5] | Vector2.new(0.5, 0.5) |
| UDim | [scale, offset] | "CornerRadius": [0.25, 0] | UDim.new(0.25, 0) |
| UDim2 | [xScale, xOffset, yScale, yOffset] | "Size": [0.5, 0, 0, 40] | UDim2.new(0.5, 0, 0, 40) |
| CFrame | [x, y, z] | "CFrame": [0, 10, 0] | CFrame.new(0, 10, 0) |
| NumberRange | [min, max] | "Lifetime": [1, 3] | NumberRange.new(1, 3) |
| Rect | [minX, minY, maxX, maxY] | "SliceCenter": [10, 10, 20, 20] | Rect.new(10, 10, 20, 20) |
| asset | text | "Image": "rbxassetid://123" |
Numbers, text, and true or false
These go straight through as they are.
"Transparency": 0.5,
"Text": "Play",
"Anchored": true,
"LayoutOrder": 3
Booleans must be real JSON true or false, with no quotes. The text "true" is read as false.
Enums
Write just the name of the item. RoFlux already knows which enum the property uses, so you leave off the Enum.Material. part.
"Material": "Neon",
"TextXAlignment": "Left",
"Font": "GothamBold",
"ScaleType": "Fit"
Names are case sensitive. "Neon" works and "neon" does not. Writing the full "Enum.Material.Neon" does not work either.
You can also give the number value, so 288 means the same as "Neon". Names are much easier to read, though.
To find the right name, click the property in Studio's Properties window. The dropdown lists every item it accepts.
Colors
Color3
Three numbers, for red, green and blue.
"Color": [255, 200, 40] -- 0 to 255, like Color3.fromRGB
"Color": [1, 0.78, 0.16] -- 0 to 1, like Color3.new
"Color": "#FFC828" -- hex, when syncing
RoFlux picks the scale for you. If any of the three numbers is above 1, all three are read as 0 to 255. If all three are 1 or below, they are read as 0 to 1.
[1, 0, 0] is bright red, not almost black, because nothing in it is above 1. A mix like [0.5, 200, 0] is read as 0 to 255, so the 0.5 becomes almost nothing. Keep all three numbers on the same scale.
Hex needs all six digits. The # is optional. Short hex like "#F00" is not read.
BrickColor
The BrickColor name as text, like "Bright red" or "Really black". Its number works too.
Vector3 and Vector2
"Size": [4, 1, 2] -- Vector3.new(4, 1, 2)
"Position": [0, 10, 0]
"AnchorPoint": [0.5, 0.5] -- Vector2.new(0.5, 0.5)
Any number you leave off becomes 0, so [4, 1] on a Vector3 gives 4, 1, 0.
Inside $Properties you can also write { "x": 4, "y": 1, "z": 2 }, with lowercase names.
Vector3int16 and Vector2int16 take the same form.
UDim
One axis of a UI size, written as scale then offset. Scale is a fraction of the parent. Offset is pixels.
"CornerRadius": [0.25, 0] -- UDim.new(0.25, 0)
"PaddingLeft": [0, 12] -- UDim.new(0, 12)
You see UDim on UICorner, UIPadding, the Padding of a UIListLayout, and similar.
UDim2
This is the one people mix up the most. It is four numbers, in the same order as UDim2.new:
[ xScale, xOffset, yScale, yOffset ]
That is X scale, then X offset, then Y scale, then Y offset. It is not X, Y, X, Y.
| In Luau | In RoFlux |
|---|---|
UDim2.new(0.5, 0, 0.5, 0) | [0.5, 0, 0.5, 0] |
UDim2.fromScale(0.5, 0.25) | [0.5, 0, 0.25, 0] |
UDim2.fromOffset(200, 50) | [0, 200, 0, 50] |
UDim2.new(1, -20, 0, 40) | [1, -20, 0, 40] |
A handy way to remember it: fromScale(x, y) puts a 0 after each number, and fromOffset(x, y) puts a 0 before each number.
You can also write it as two UDims, which some people find easier to read:
"Size": [[0.5, 0], [0.25, 0]]
Inside $Properties there is a named form as well, { "ScaleX": 0.5, "OffsetX": 0, "ScaleY": 0.25, "OffsetY": 0 }.
CFrame
Three numbers give just a position:
"CFrame": [0, 10, 0] -- CFrame.new(0, 10, 0)
To include rotation, give all twelve numbers that CFrame:GetComponents() returns. That is the position, then the nine numbers of the rotation.
"CFrame": [0, 10, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]
The easy way to get these is to select the part, run print(workspace.Part.CFrame:GetComponents()) in the command bar, and copy what it prints.
Ranges and sequences
NumberRange
"Lifetime": [1, 3] -- NumberRange.new(1, 3)
When syncing, a single number also works, and sets the min and max to the same value.
NumberSequence
A single number gives a flat value. For a curve, give a list of points. Each point is [time, value], with an optional third number for the envelope.
"Transparency": 0.5
"Transparency": [[0, 0], [0.5, 0.3], [1, 1]]
ColorSequence
A list of [time, color] points. Each color can be hex or three numbers.
"Color": [[0, "#FF0000"], [1, [0, 0, 255]]]
Give at least two points, with the first at time 0 and the last at time 1. Roblox rejects a sequence that does not run from 0 to 1, and the sync stops with an error. A sequence with only one point is ignored and comes out flat, as 0 or black.
Fonts
Text objects have two font properties, and they take different things.
Font is the older enum, so it takes a name:
"Font": "GothamBold"
FontFace is the newer Font type. Give it the font family, and if you like a weight and a style. Because the value is an object, it has to go inside $Properties:
"$Properties": {
"FontFace": {
"family": "rbxasset://fonts/families/GothamSSm.json",
"weight": "Bold",
"style": "Italic"
}
}
Weight is a FontWeight name such as "Regular", "SemiBold" or "Bold". Style is "Normal" or "Italic". Both are optional.
Attributes
Attributes have no fixed type, so RoFlux cannot look one up. It goes by the shape of the value instead.
| You write | You get |
|---|---|
"text" | string |
12 | number |
true | boolean |
[1, 2, 3] | Vector3 |
[1, 2] | Vector2 |
Anything else, like a color, needs $Type. Otherwise it is skipped.
"$Attributes": {
"Tint": { "$Type": "Color3", "$Value": [255, 0, 0] }
}
Saying the type yourself
When you want to be exact, wrap the value in $Type and $Value:
"Color": { "$Type": "Color3", "$Value": [255, 0, 0] }
An object holding $Type is always a property, never a child, so this is safe in the shorthand too. It is mostly useful for attributes, since a normal property already knows its own type.
$Type can be any of these: string, number, boolean, Color3, BrickColor, Vector3, Vector2, Vector3int16, Vector2int16, UDim, UDim2, CFrame, Rect, NumberRange, NumberSequence, ColorSequence and Font. Enums are not on the list. For those, just write the name.
Syncing and place files
Syncing converts values inside Studio, using the live property. roflux build converts them on its own, from a list of every Roblox property. Most types work the same both ways. A few are not handled by roflux build yet, and come out empty or at their default in the place file.
| Written as | Syncing | roflux build |
|---|---|---|
| Arrays for vectors, UDim, UDim2, Color3, CFrame and Rect | yes | yes |
| Enum names and numbers | yes | yes |
Objects inside $Properties, like { "x": 4 } | yes | yes |
Hex colors like "#FF0000" | yes | no, comes out black |
$Type values | yes | no |
Named UDim2 like { "ScaleX": 0.5 } | yes | no, comes out zero |
| A single number for a NumberRange | yes | no, comes out zero |
| NumberSequence and ColorSequence | yes | no |
FontFace | yes | no |
| Vector3int16 and Vector2int16 | yes | no |
| Attributes that are text, numbers, booleans or Vector3 | yes | yes |
Vector2 and $Type attributes | yes | no |
If you build place files, the safe choice is the array form for everything. That is the same advice as the rule at the top of this page.
When a value does not work
Open the Changes panel in Studio and pick the Failed filter. Each failure names the instance and says what went wrong.
| Message | What it means |
|---|---|
Part has no property "Colr" | The property name is wrong for that class. Check the spelling and the capitals. |
could not read a value for "Size" | The value is the wrong shape for its type. Compare it with this page. |
"AbsoluteSize" would not accept its value | The shape was fine but Roblox refused it, usually because the property is read only. |
If a property quietly did nothing and there is no failure at all, check the rule at the top first. An object in the shorthand makes a child instance instead of setting the property.