Skip to content

Value grammar

This page defines the grammar of attribute values in EBNF, using the same notation as the XML 1.0 specification. Which attribute is read with which rule is in Rules per attribute at the end.

NotationMeaning
A ::= …Definition of rule A
"text"That sequence of characters
[0-9]One character in the range
[^…]One character other than those listed
A?0 or 1 times
A*0 or more times
A+1 or more times
A BA followed by B
A | BA or B
A - BA, except what matches B
#x20A space (U+0020)
/* … */Comment
[MOCHInnnn]The diagnostic number reported when the rule isn’t met. For props written on a part tag and for <Prop default>, any value that doesn’t fit the type gives MOCHI3006
Line breaks and tabsBy the XML rules, line breaks and tabs in an attribute value are replaced with spaces (#x20) before the value is read. Write a line break as &#10; (text="First line&#10;Second line")
Character references&quot;, &amp;, and so on are read after XML turns them back into characters
AttributeValue ::= Escaped | Binding | Plain
Escaped ::= ( "{{" Char* ) - ( "{{" Char* "}}" Char* ) /* becomes the text with the first "{" removed */ [MOCHI5002]
Binding ::= "{" S* Reference S* "}" [MOCHI5002]
Plain ::= [^{]* /* contains no "{" */ [MOCHI5002]
Char ::= /* any one character */
S ::= /* whitespace */
PlainRead as a value of the attribute’s type (a number, a Vector3, a path, and so on)
BindingReads the value of a prop or a <For> row and converts it to the attribute’s type (Binding)
EscapedThe form for text that starts with {. Only the first { is removed and nothing else is changed. "{{draft}" is the text {draft}, and "{{score} pts}" is {score} pts}
A value that starts with {{ and has }} after it"{{score}}" and "{{score}} pts" are MOCHI5002 (that }} would stay as it is and give {score}} pts). Write "{{score}" for {score} and "{{score} pts" for {score} pts. A text that starts with { and contains }} cannot be written this way
Assets/Example/Notes.mochi.xml
<Notes prefab="true">
<Object name="{{draft}"/>
</Notes>
SyntaxNumberExample
A value that starts with {{ and ends with }}MOCHI5002literal-brace-closing
A value that starts with {{ and has }} in the middleMOCHI5002literal-brace-closing-middle

A binding reads the value of a prop or a <For> row by writing the attribute value as {name} or {row.column}.

Binding ::= "{" S* "!"? S* Reference S* "}" [MOCHI5002]
/* "!": the opposite of a bool value (also a value that changes at runtime) */
Reference ::= Name ( "." Name )? [MOCHI5002]
/* one Name: a prop (in a part with a T# script, also a C# member) */
/* Name "." Name: a <For> row and one of its columns */
/* Name "(" arguments ")": a function call (only in a part with a T# script) */
Where it can appearThe entire value. It can’t appear partway through text, as in name="Room {n}" or position="0 {y} 0"
Names that can be readOnly the props of the same file and the <For> rows of the same file (Name scope). In a part with a T# script, other names are read as C# members of that part (Value that changes at runtime)
Whitespace inside { and }Skipped. { title } is the same as {title}
Just a row nameWriting just a row name, as in {art}, is an error. Write the column too ({art.title})
A name or column that isn’t foundMOCHI5001.
Inside a defaultA binding can’t be written
Function calls{IsCurrent(art.index)} calls a C# method of a part with a T# script (Value that changes at runtime). In a part without a T# script it is MOCHI5002, and MOCHI8001 where T# is not available
Negation{!featured} is the opposite of a bool value. A value that isn’t a bool gives MOCHI5002; a value that changes at runtime and isn’t a bool gives MOCHI3006
Assets/Example/Rooms.mochi.xml
<Rooms prefab="true">
<For each="art" in="folder('../Gallery/art/')">
<Object key="{art.key}" name="Room {art.title}"/>
</For>
</Rooms>
SyntaxNumberExample
A binding partway through textMOCHI5002binding-in-text
{} with no nameMOCHI5002binding-empty
A binding with two .MOCHI5002binding-two-dots
A binding to a prop name containing -MOCHI5002binding-name-hyphen
A row name without a columnMOCHI5002row-without-column
Reading the caller’s <For> row from inside a partMOCHI5001caller-row-not-visible
A binding inside a defaultMOCHI5001default-with-binding
A binding that calls a functionMOCHI5002binding-call
Name ::= NameStart NameChar*
NameStart ::= Letter | "_"
NameChar ::= Letter | Digit | "_"
Letter ::= /* a Unicode letter (including Japanese characters) */
Digit ::= /* a Unicode decimal digit */
Where it’s usedNotes
Names and columns in bindings{title}, {art.title}. <Prop name> and table column names can contain other characters, but a binding can read only names of this form
<For each>The row’s name
<Slot name> and the content’s slotThe name of the <Slot>
Props of a part with a T# scriptThey also have the C# identifier (ASCII) constraint (Name constraints)
Number ::= Sign? ( Digits ( "." Digits? )? | "." Digits ) [MOCHI1009]
Sign ::= "+" | "-"
Digits ::= [0-9]+
Int ::= Number /* a number whose fractional part is 0; "2.0" is 2 */ [MOCHI1009]
Decimal numbers1.5, -2, +1, .5, and 2. can be written
Unsupported formsExponent notation (1e3), digit separators (1,000), leading or trailing whitespace, NaN, and Infinity. Only a component’s float attributes take Infinity and -Infinity
int valuesA number whose fractional part is 0. 2.0 is read as 2
Digits written to the prefabRounded. position and the RectTransform values are written to 4 decimal places, and scale, rotation and component values to 6
Assets/Hall/Hall.mochi.xml
<Hall prefab="true">
<Props>
<Prop name="題名" type="string" default="Welcome"/>
<Prop name="count" type="int" default="2.0"/>
</Props>
<Object name="{ 題名 }" position="+1 .5 2." scale="1 1 1" static=""/>
<Grid columns="{count}">
<Object size="1 1 0"/>
</Grid>
<Object name="Lamp">
<Light color="#ffe6cc80"/>
</Object>
</Hall>
Vector3 ::= Sp* Number Sp+ Number Sp+ Number Sp* [MOCHI1009]
Sp ::= #x20
SeparatorSpaces only. Any number of spaces in a row is fine, and leading and trailing spaces are skipped. Commas can’t be written
Color ::= "#" Hex Hex Hex Hex Hex Hex ( Hex Hex )? [MOCHI1009]
Hex ::= [0-9A-Fa-f]
ComponentsTwo digits each, in R, G, B, A order; each component is the hexadecimal value ÷ 255
Omitting alphaIn #RRGGBB, alpha is 1 (FF)
Unsupported formsColor names (orange), three-digit #FFF, and rgb(…)
Bool ::= "true" | "false" [MOCHI1009]
CaseCase-sensitive. True, FALSE, 1, and 0 can’t be written
String ::= Char* /* text that starts with "{" is written as "{{" */
Text ::= String - "" /* name and key: not empty, no control characters */ [MOCHI1009]
name and keyAn empty value and a value with control characters can’t be written
Number and bool valuesA number or bool read through a binding is read as its text
SyntaxNumberExample
A number in exponent notation (1e3)MOCHI1009number-exponent
A comma-separated Vector3MOCHI1009vector-comma
A Vector3 with two numbersMOCHI1009vector-two-numbers
A color name (orange)MOCHI1009color-name
A three-digit color (#FFF)MOCHI1009color-short
False starting with a capital letterMOCHI1009bool-capital
An empty nameMOCHI1009name-empty
Path ::= PathChar+ /* can't start with "/" */ [MOCHI2001]
PathChar ::= [^\:] /* anything but "\" and ":" */ [MOCHI2001]
A path starting with Assets/ or Packages/A path from the project root. It’s case-sensitive, so assets/ is treated as a relative path
Any other pathA path relative to the folder of the file it is written in. A path written in a column of a table (the file column, and any other column used as a path) is relative to the table file
A path passed to a partResolved from the caller’s file
A path in a prop’s defaultResolved from the part’s file
., .., and empty segments. and // are skipped, and .. is the parent folder
Outside the projectA path that points outside Assets/ and Packages/ can’t be written (MOCHI2001)
Names starting with builtin:Not paths. They contain :, so writing one where a path goes gives MOCHI2001
Checking what it points toA missing file gives MOCHI2002, a missing .meta gives MOCHI2009, and the wrong kind of asset gives MOCHI2008
Assets/Example/Entrance.mochi.xml
<Entrance prefab="true">
<Prefab src="Assets/Kit/KitFrame.prefab" name="FromRoot"/>
<Prefab src="../Kit/KitFrame.prefab" name="FromHere" position="1 0 0"/>
</Entrance>

In this example, the part Picture is in Assets/Parts/; the passed image path resolves from Assets/Gallery/Wall.mochi.xml, and the default image path resolves from Assets/Parts/Picture.mochi.xml.

Assets/Gallery/Wall.mochi.xml
<Wall prefab="true">
<Picture name="Left" label="Sea" image="art/01_Sea.png"/>
<Picture name="Right" label="Moon" position="2 0 0"/>
</Wall>
<!-- file: Assets/Parts/Picture.mochi.xml -->
<Picture>
<Props>
<Prop name="label" type="string"/>
<Prop name="image" type="Texture" default="../Gallery/art/02_Moon.png"/>
</Props>
<Object name="{label}">
<MeshFilter mesh="builtin:Quad"/>
<MeshRenderer material="../Art/Frame.mat" mainTexture="{image}"/>
</Object>
</Picture>
SyntaxNumberExample
A path separated with \MOCHI2001path-backslash
A path that points outside Assets/MOCHI2001path-outside

The data you can write in <For>’s in comes in 2 kinds: folder('…') and table('…').

DataSource ::= S* ( "folder('" DataPath "')" | "table('" DataPath "')" ) S* [MOCHI2007]
DataPath ::= [^']* /* resolved as a Path */ [MOCHI2001]
RowsOne row per image directly inside the folder. Subfolders are not looked into
Image extensions.png, .jpg, .jpeg, .tga, .psd, .exr, .hdr, .bmp, .gif, .tif, .tiff. Case-insensitive
OrderOrdinal string comparison of file names. 10.png comes before 2.png
PathResolved from the folder of the file that wrote in
No such folderMOCHI2003.
ColumnsValue
fileThe image’s path, from the project root
nameThe file name without its extension
titlename with a leading number and separator (_, -, space, .) removed. 01_Sea becomes Sea
keyThe file name, including its extension. This row’s key
indexThe order, counted from 0
Assets/Gallery/Room.mochi.xml
<Room prefab="true">
<For each="a" in="table('../Data/art.csv')">
<Object name="{a.title}" key="{a.key}">
<MeshFilter mesh="builtin:Quad"/>
<MeshRenderer material="../Art/Frame.mat" mainTexture="{a.file}"/>
</Object>
</For>
</Room>
Format.csv or .json (the extension is case-insensitive). Any other extension gives MOCHI2007
CSVThe first line is the header. Wrapping in " lets a cell contain , and line breaks, and "" is a single ". Whitespace around a cell stays in the value. All values are string
JSONA flat array of objects. Values are text, numbers, or true/false. Numbers may also use exponent notation (1e3)
A row’s keyIf there’s an id column, its value; otherwise, the text in the file column. A table with an id column must fill in id on every row. In JSON, if any row has an id, every row needs one
The file columnResolved from the table’s file, and its existence is checked. Read through a binding, it’s a path from the project root
Reserved column nameskey and index can’t be column names. Give a row’s key with an id column
Automatically added columnskey and index (same meaning as in folder())
OrderThe order written in the table
Assets/Example/Index.mochi.xml
<Index prefab="true">
<For each="r" in="table('rooms.csv')">
<Object name="{r.title}" key="{r.key}"/>
</For>
</Index>
<!-- file: Assets/Example/rooms.csv -->
id,title
east,"East Room, upstairs"
west,West Room
Assets/Example/Index.mochi.xml
<Index prefab="true">
<For each="r" in="table('rooms.json')">
<Object name="{r.title}" key="{r.key}" active="{r.open}"/>
</For>
</Index>
<!-- file: Assets/Example/rooms.json -->
[
{ "id": "east", "title": "East Room", "open": true },
{ "id": "west", "title": "West Room", "open": false }
]
SyntaxNumberExample
An argument in double quotesMOCHI2007data-source-double-quote
A column named keyMOCHI2005table-key-column
A table with neither an id nor a file columnMOCHI2006table-row-without-key
A row with an empty idMOCHI2006table-empty-id
Static ::= Sp* ( StaticWord ( Sp+ StaticWord )* )? Sp* [MOCHI1009]
StaticWord ::= "lighting" | "occluder" | "batching" | "occludee" | "reflection"

There are 5 words, and each maps to one Unity static flag. The flags are set only on the GameObject they are written on, not on the GameObjects under it (write them on each one to set them there too).

WordUnity flag
lightingContribute GI
occluderOccluder Static
batchingBatching Static
occludeeOccludee Static
reflectionReflection Probe Static
EnumValue ::= EnumName [MOCHI1009]
ComponentEnum ::= Sp* EnumName ( Sp+ EnumName )* Sp* [MOCHI1009]
/* two or more names only for combinable ([Flags]) enumerations */
EnumName ::= /* a name from the attribute's list, case-sensitive */
AttributesRuleName
align of <Row> and <Grid>EnumValuebottom・center・top
overflow of <Prefab>EnumValuerepeat
Component attributesComponentEnumThe names in each table of Component list. They can’t be written as numbers
PrefabPath ::= "" | ObjectName ( "/" ObjectName )* [MOCHI2010]
ObjectName ::= [^/]+ /* the name of a GameObject inside the prefab */
FillPattern ::= ( [^{/*] | "*" )+ /* "*" matches any sequence of characters, including none */ [MOCHI1009]
PrefabPathWritten in <At path> and <Slot path>. Names from the prefab’s root, separated by /; an empty string is the root. At each step, the name must match exactly one GameObject. The inside of a prefab nested in the prefab can’t be addressed
FillPatternWritten in <Prefab fill>. Compared with the whole GameObject name
PropType ::= "bool" | "int" | "float" | "string" | "Vector3" | "Color" | "Texture" | "Material" | "GameObject" | "Object" [MOCHI3006]
Prop typeValues that can be written
boolBool
intInt
floatNumber
stringString. A number or bool read through a binding becomes its text
Vector3Vector3
ColorColor
TexturePath. An image, a Texture2D saved as an .asset, or a .renderTexture
MaterialPath。.mat
GameObjectPath. A prefab or a model
ObjectA path to a GameObject in the same prefab (table below)
Asset checksFor Texture, Material, and GameObject, the file and its .meta must exist (a missing .meta gives MOCHI2009). The kind of asset Unity imported is also checked (a mismatch gives MOCHI2008)
A value that doesn’t fit the typeMOCHI3006.
Object valuesThe path written where the part is used is counted from there: a relative path from the GameObject of the element that uses the part, a path starting with / from the root of that file
Where an Object can be writtenInside the part, as the whole value of an attribute that points to an object in the same prefab or of a public variable of an attached <UdonBehaviour> that holds an object, and as the path of a UnityEvent item (onClick="{target}:Open"). It can also be passed as is to another part’s Object prop. Anywhere else it is MOCHI3006
Object errorsNo object at the path (MOCHI2015) or no component of the attribute’s type (MOCHI2016) is reported where the path is written

Built-in attributes are read with the following 32 rules.

ElementsAttributesRuleBinding
Hostname・keyTextAllowed
Hostposition・rotation・scaleVector3Allowed
HostsizeVector3 (each 0 or more)Allowed
HostpivotVector3 (each 0 to 1)Allowed
HostactiveBoolAllowed (including values that change at runtime)
HoststaticStaticAllowed
Root elementprefabBoolNot allowed
Root element of an entry pointwalkFromVector3Not allowed
Root element of an entry pointplayerRadiusOne Number (at least 0.1)Not allowed
Root element of an entry pointplayerHeight・minPassageWidthOne Number (greater than 0)Not allowed
<Prefab>srcPath(.prefab)Allowed
<Prefab>fillFillPatternNot allowed
<Prefab>overflow"repeat"Not allowed
<Prefab>gapVector3Allowed
<Row>spacingOne Number (0 or more)Allowed
<Grid>spacingOne Number, or two separated by #x20 (each 0 or more)Allowed
<Row>・<Grid>alignEnumValueAllowed
<Grid>columnsInt(1〜10000)Allowed
<For>eachNameNot allowed
<For>inDataSourceNot allowed
<If>testBool (a value fixed at generation time; otherwise MOCHI5003)Allowed
<Slot>nameNameNot allowed
<Slot>pathPrefabPathNot allowed
Content elementslotNameNot allowed
<At>pathPrefabPathNot allowed
<At>activeBoolAllowed (including values that change at runtime)
<Prop>nameStringNot allowed
<Prop>typePropTypeNot allowed
<Prop>defaultA value of the type’s type (not for Object)Not allowed (Escaped can be written)
<Prop>runtimeBoolNot allowed
Part tagpropsA value of the prop’s type (Prop values)Allowed
Component tagC# property nameThe types in Component listAllowed (inside a part with a T# script, also values that change at runtime)