Nubu
  • Features
  • How it works
  • Pricing
  • Integrations
  • FAQ
  • Contact
  • Docs
  • Blog
  • Log in
  • Log inSign up
    Nubu

    Creative automation for teams that ship campaigns, not busywork.

    Try for free
    Product
    FeaturesNubu MotionHow it worksPricingIntegrationsFAQ
    Company
    AboutContactDocsBlogLog in
    Legal
    Privacy policyTerms of serviceData deletion
    © 2026 Bear Studios · Nubu
    Introduction
    Templates overviewInstalling Nubu BuilderAdding template compsAdding propertiesAdding footageSetting defaultsExporting your templateUploading a template
    Flows overviewAvailable nodesAdding a nodeConnecting nodesWorking with dataTemplates and outputsUsing AI nodesBuilding a creative
    CampaignsTemplatesAssetsGlossariesRendersSettings
    Connecting Meta AdsConnecting Google AdsConnecting OpenAIConnecting Gemini AI StudioConnecting Anthropic
    AI Assistant overviewPrompt examplesAssistant settings and controls
    Nubu Motion scripts: the reference
    OverviewQuick startDifferences from After EffectsDeterminism
    JavaScript supportReferences and idsProject scriptsState and timeBudgets and errorsFormatting values
    GlobalTime conversionInterpolationVector mathsRandom and noiseColour conversionOther maths
    LayerCompPropertyKeyframePathGeometryProjectComponentConsoleComponentControlExpressionControl
    The property vocabularyAnimators propertiesAudio propertiesContent propertiesContents propertiesEffects propertiesExpression controls propertiesFills propertiesInstance controls propertiesLayer propertiesLayout propertiesMasks propertiesStrokes propertiesText style propertiesTransform propertiesTrim path properties
    Error codesBudgets
    Changelog
    All docs
    Motion Scripting
    / Introduction

    Determinism

    The four rules that make a scripted frame render byte for byte the same in the editor, on the farm and on every machine.

    A script's job is to produce pixels that can be trusted: what you scrub in the editor is what the farm renders, byte for byte, on any machine, any number of times. That promise is engineered, not hoped for, and it rests on four rules.

    One engine, everywhere#

    The same JavaScript engine is embedded in the editor and in the render farm, configured identically. There is no "it worked in preview" gap: the editor's evaluation IS the render's evaluation. Even the maths library is pinned - the engine ships its own, so Math.sin returns bit-identical results on macOS, Linux and in the browser, rather than whatever each platform's C library fancies.

    The sandbox admits no outside world#

    Scripts cannot reach the network, storage, timers or the wall clock. Date reports the comp's time, not your watch; Math.random is the seeded stream described below. With no doors to the outside, a frame's value can only depend on the document and the frame number - which is exactly what makes it reproducible.

    Randomness is seeded#

    random(), gaussRandom(), noise() and wiggle() all derive from a seed built out of the document's expression seed, the script and the frame. The scatter at frame 7 is the same scatter on every playback, every scrub and every render - and changing the document seed re-deals every pattern at once. seedRandom(offset) lets a script pick its own stream; noise and wiggle are pure functions of their inputs, safe to sample at any time in any order.

    Scrubbing equals playing#

    Anything a script remembers through state() folds deterministically from the first frame: to show frame 200, the engine has (conceptually) evaluated frames 0 through 199 first, so jumping to a frame and playing into it produce the same picture. There is no hidden "simulation ran while you watched" state to lose. The State and time page describes the fold and its rules.

    Together these rules mean a Motion document is a pure function from (document, frame) to pixels - the property everything else in the render pipeline leans on, from frame caching to farm dedupe.