Component
A Component is the stable proxy a car vends for one of its definition components, reached via car.components["SomeComponentId"] (indexed through a ComponentIndex). The proxy persists across hydrate/dehydrate: persistent state (enabled, localProperties) is always valid, while live/material capabilities require the component to be hydrated (hydrated == true).
Typed subclasses add their own capabilities on top of the base proxy surface:
RendererGroupComponent— owns a colorizer and exposes a single sharedmaterial(Material).DecalComponent— wraps a decal projector and exposes itsmaterial(Material).
Accessing Components
Section titled “Accessing Components”car.components is a ComponentIndex. Index it with a component’s definition key — its id within the object definition’s components map (e.g. "LoadModelVolume"), which is distinct from the component’s display name. If the key isn’t found, indexing logs a warning and returns null.
The value returned is typed by the component’s kind: a renderer-group component comes back as a RendererGroupComponent, a decal component as a DecalComponent, and everything else as the base Component.
var pilot = car.components["boiler-tube-pilot"]if pilot != null { pilot.enabled = car.properties["customize.pilot"] == "boilertube"}Properties
Section titled “Properties”enabled
bool The component’s persistent enabled intent. Setting it hydrates (true) or dehydrates (false) the component, and the value survives model reloads. Always valid — works regardless of hydration.
hydrated
bool Whether the component is currently hydrated (its GameObject and material are live). Read-only, never throws — use it to guard material access (if c.hydrated { ... }).
localProperties
Properties Per-instance key-value store for publishing runtime state that Relay scripts can query — e.g. a LoadModelVolume component publishes its current load’s identifier and tags here, so a script can read car.components["LoadModelVolume"].localProperties["loadModel"].
RendererGroupComponent
Section titled “RendererGroupComponent”Extends Component. Owns a CarColorizer and exposes the renderer group’s shared material. A renderer group shares one material across all of its renderers, so material is singular.
The group’s live material, as a transient Material facet. Throws if the component is not hydrated (no material exists yet). Hold onto the Component proxy instead, and fetch material again each time you need it.
enabled bool false to relinquish automatic color writes to the script, true to restore the built-in behavior Relinquish or restore the built-in colorizer’s automatic _BaseColor writes, so a script can own the material’s color instead. Not sticky across hydration — re-assert it (e.g. in response to a hydrate event) each time the component hydrates.
DecalComponent
Section titled “DecalComponent”Extends Component. Wraps a DecalProjector and exposes its material, through which a script configures the paint-map/image mode and sets its content.
© 2026 Giraffe Lab LLC. All rights reserved.