Component Scripts
Add local UI behavior and read game values with TypeScript.
You can make a button send an action to Blueprint without a script. Add TypeScript when a component needs local behavior, such as expanding details, selecting a tab, or combining game values for display.
Start with Keep a local toggle. It contains a complete component that you can save and click in Preview.
Make names available to the template
Write code in one <script lang="ts"> section and return the values and
functions that the template uses. A function that is declared but not returned
cannot be called by @click.
| Function | What it does |
|---|---|
state | Holds a value private to this component copy |
computed | Calculates a value from other values and updates it when they change |
watch | Runs a callback when the watched value changes; returns a stop function |
onMount / onUnmount | Runs code when a component is created or removed |
onShow / onHide | Runs code when visibility changes |
timers.setTimeout / timers.setInterval | Schedules local UI work |
Read a game value
First define the field in Store. In the script,
type /, choose Store → Read field, and select your field. Studio adds the
@calmui/store import if needed.
Use the generated field path in a computed value and return it for the template.
For example, after defining a string field player.name:
import { defineComponent, computed } from "@calmui/runtime";
import { store } from "@calmui/store";
export default defineComponent<Record<string, unknown>, unknown>(() => {
const playerName = computed(() => store.player.name);
return { playerName };
});The template can display {{ playerName }}. In Studio, supply a preview preset;
in the game, write the field from Blueprint.
Localize text in a script
Template text uses $loc('Table::Key', 'Default'), but it cannot fill in a
value at runtime. When a localized string needs a runtime value - a count, a
player name - import loc from @calmui/runtime instead:
import { computed, defineComponent, loc } from "@calmui/runtime";
import { store } from "@calmui/store";
export default defineComponent<Record<string, unknown>, unknown>(() => {
const greeting = computed(() =>
loc("GameUI::Welcome", "Welcome back, {name}!", { name: store.player.name })
);
return { greeting };
});loc(key, fallback, params?) takes the same literal key and literal default
$loc does - Studio's Languages panel lists a script loc() key exactly like
a template $loc key, and the two share the same conflict check if they ever
disagree on a default for the same key. params is an object of {name}
values substituted into the resolved (or fallback) text after translation -
{{ and }} write a literal {/}, and a name missing from params is
left as {name} and logged as a Problem in Development. Numbers convert the
same way they do everywhere else in CalmUI; loc() does not format numbers
or dates per-culture.
Bind the returned value in the template ({{ greeting }}) the same way you
bind any other computed. Save the component again after a culture or
translation changes in Preview to see the new text - the same reload Studio
already performs for a Store or prop change.
Keep gameplay in Unreal
Scripts cannot read files, use the network, or access Unreal objects directly. Send an action when gameplay must change. Save errors appear in Problems with their source location. See script limits.