Skip to content

Variables

Variables are named values you create in Unicorn Studio and publish with a scene. They are the preferred way to expose safe developer controls for a published embed, because host code can update a variable without knowing layer IDs, shader uniforms, or internal scene structure.

Use variables for:

  • Dynamically changing property values at runtime
  • Custom click, hover, scroll, and mouse animations
  • Passing data from a CMS
  • Reusable values shared across multiple layers

Avoid direct layer mutation when a variable exists for the same value.

Live Example

This embed starts with three initial variable values: Wave, Bokeh, and Text.

<div
  style="width: 100%; height: auto; aspect-ratio: 16/9"
  data-us-project="0HJ5wF7grrXdlW6gSbAD"
  data-us-vars='{"Wave":0.37,"Bokeh":0.17,"Text":"VARIABLES"}'
></div>
<script type="text/javascript">!function(){var u=window.UnicornStudio;if(u&&u.init){if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",function(){u.init()})}else{u.init()}}else{window.UnicornStudio={isInitialized:!1};var i=document.createElement("script");i.src="https://cdn.jsdelivr.net/gh/hiunicornstudio/unicornstudio.js@v2.2.0-beta6/dist/unicornStudio.umd.js",i.onload=function(){if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",function(){UnicornStudio.init()})}else{UnicornStudio.init()}},(document.head||document.body).appendChild(i)}}();</script>

Setting Initial Values

Use data-us-vars for declarative HTML embeds. The value must be a JSON object keyed by variable name.

<div
  data-us-project="YOUR_PROJECT_EMBED_ID"
  data-us-vars='{"brandColor":"#7c3aed","intensity":0.65,"heroImage":"https://example.com/hero.jpg"}'
></div>

If you create scenes in JavaScript, pass initialVariables to UnicornStudio.addScene().

const scene = await UnicornStudio.addScene({
  projectId: 'YOUR_PROJECT_EMBED_ID',
  element: document.querySelector('#unicorn'),
  initialVariables: {
    brandColor: '#7c3aed',
    intensity: 0.65,
    heroImage: 'https://example.com/hero.jpg'
  }
});

Initial variables are applied after the scene loads its authored defaults.

Updating Variables After Load

Use setVariable() for one value or setVariables() for multiple values.

scene.setVariable('brandColor', '#ff4fd8');
scene.setVariable('intensity', 0.9);

scene.setVariables({
  brandColor: '#4f46e5',
  intensity: 0.4
});

If a variable name is unknown or a value fails validation, Unicorn Studio logs a console warning and leaves the current value unchanged.

Reading Variables

const brandColor = scene.getVariable('brandColor');
const allValues = scene.getVariables();
const definition = scene.getVariableDefinition('brandColor');
const definitions = scene.getVariableDefinitions();
const manifest = scene.getVariableManifest();

Use getVariableManifest() before building custom controls. Each manifest item includes the variable name, type, default value, current value, description, validation, binding count, and binding metadata.

Listening For Changes

const unsubscribe = scene.onVariableChange((name, value, values) => {
  console.log('Variable changed:', name, value, values);
});

unsubscribe();

The callback receives the changed variable name, the new value, and the full current variables object.

Variable Types

Common variable types:

  • number: JavaScript number
  • boolean: JavaScript boolean
  • string: JavaScript string
  • color: hex string such as #7c3aed
  • vec2: object with { type: 'Vec2', x, y }
  • vec3: object with { type: 'Vec3', x, y, z }
  • texture: URL string or texture-like object, depending on the authored binding

Color variables should usually be set as hex strings:

scene.setVariable('brandColor', '#0ea5e9');

Vector variables should include the vector type:

scene.setVariable('position', { type: 'Vec2', x: 0.5, y: 0.35 });
scene.setVariable('direction', { type: 'Vec3', x: 0.2, y: 0.8, z: 0.1 });

Build Custom Controls

Use the manifest to generate app UI from the variables that were actually published with the scene.

function createControls(scene, container) {
  scene.getVariableManifest().forEach(variable => {
    const input = document.createElement('input');
    input.name = variable.name;

    if (variable.type === 'color') {
      input.type = 'color';
      input.value = variable.currentValue || variable.defaultValue || '#ffffff';
    } else if (variable.type === 'number') {
      input.type = 'range';
      input.min = variable.validation?.min ?? 0;
      input.max = variable.validation?.max ?? 1;
      input.step = variable.validation?.step ?? 0.01;
      input.value = variable.currentValue ?? variable.defaultValue ?? 0;
    } else if (variable.type === 'boolean') {
      input.type = 'checkbox';
      input.checked = Boolean(variable.currentValue ?? variable.defaultValue);
    } else {
      input.type = 'text';
      input.value = variable.currentValue ?? variable.defaultValue ?? '';
    }

    input.addEventListener('input', () => {
      const value = input.type === 'checkbox' ? input.checked : input.value;
      scene.setVariable(variable.name, value);
    });

    container.append(input);
  });
}

Breakpoints And Events

Runtime precedence for a property is:

authored base value -> breakpoint value -> variable/runtime override -> active event animation

In practice, breakpoints choose the default, variables let host code control that default, and events animate on top of that value while they are active.

Debugging

Start by checking the variables published with the scene:

console.table(scene.getVariableManifest());
console.log(scene.getVariables());

If setVariable() does nothing:

  • Confirm the variable name exists in getVariableDefinitions().
  • Confirm the variable has at least one binding in getVariableManifest().
  • Confirm the value type matches the variable type.
  • Confirm the published scene includes the variable and its binding.

See Also