Skip to content

Getting started with components

This guide walks through a typical turn-based RPG battle setup: enemies with HP, a visible health bar, stats, teams, and turn order. You can follow it entirely in the editor—no code required.


1. Attach components to an object

  1. Select a character or enemy on the stage (Arrange workspace).
  2. In the Inspector, open the Components card.
  3. Click + Add Component.
  4. Search or scroll the menu (grouped by category: Combat, UI, Items).
  5. Pick Health, then add Health Bar if you want a bar above the sprite.

The menu lists every registered component. Already-attached types are hidden. If a component is required by another (Health Bar requires Health), attaching it auto-adds the dependency.


2. Configure fields

Each component card shows typed fields:

ComponentFields to set
HealthHP, Max HP, Invulnerable, Refill on play
Health BarWidth, colors, “Only on hover/damage”, low-HP threshold
StatsAttack, Defense, Speed
Combat ActionPower, minimum damage, variance, friendly fire
TeamTeam name (player, enemy, neutral)

Changes save with the scene. In Play, Health can refill to max when “Refill on play” is enabled.


3. Required components and the lock icon

Some components declare requires: ["health"]. Health Bar is an example:

  • Attaching Health Bar automatically attaches Health if it’s missing.
  • You cannot remove Health while Health Bar is still attached—the remove button shows a lock and tooltip (“Required by Health Bar”).

Detach dependents first, then remove the base component.


4. Wire behavior in Object Flow

Components expose actions and conditions to flow graphs.

  1. Select the object.
  2. Switch to Object Flow.
  3. Pick an event (e.g. On Tap) or create a flow.
  4. In the node catalog, open the Components section.
  5. Add nodes such as:
    • health.damage (action) — set Amount in the Flow Inspector.
    • combatAction.attack (action) — set Target, optional End turn / Turn queue.
    • health.isAlive (condition) — branch before playing a death animation.

Graph labels show health.damage and health.isAlive so you can scan the canvas quickly.

Example: tap to damage self (test)

text
On Tap → health.damage (amount: 5)

Example: only react if alive

text
On Tap → health.isAlive?
           ├─ true  → Play Audio / Set State / …
           └─ false → (nothing)

Use target in the graph when the action should run on another object (e.g. the selected enemy). Component actions resolve against the host object of the graph unless you parameterize a different reference.


5. Turn-based battle layout

A simple structure:

text
Scene
├── BattleController (empty object or icon)
│     └── Turn Queue  (group: "Combatants", order: speedDesc)
├── Hero (group: Combatants, team: player)
│     ├── Health, Stats, Combat Action, Health Bar
│     └── Object Flow: On Tap → …
└── Enemy Slime (group: Combatants, team: enemy)
      ├── Health, Stats, Combat Action, Health Bar
      └── Object Flow: …

Turn Queue

Attach Turn Queue to a controller object:

  1. Set Group to Combatants (same string as each fighter’s Group in the inspector).
  2. Set Order to speedDesc to sort by Stats speed, or registered / random.
  3. In Object Flow (scene or controller object):
    • On scene start → turnQueue.rebuild
    • On button / phase change → turnQueue.next

Events turnStart, turnEnd, roundStart, and queueEmpty can drive UI or “whose turn” highlights.

Turn Queue skips visible objects with Health at 0 HP by default, so defeated battlers do not keep acting. If the battle started with multiple Team values, it emits battleEnd and stops once only one team remains.

Attacks

Attach Combat Action to the attacker. For an enemy-tap player attack, run combatAction.attack on the hero, set Target to the tapped enemy (__actor), and enable End turn with the BattleController as the Turn queue. For an enemy AI turn, run the same action on that enemy with Target set to the hero.

Teams

Attach Team to each fighter. Use conditions Is Ally Of / Is Enemy Of with an object reference before applying damage in a graph.

Ability cooldown

Attach Ability Cooldown to a hero skill object or the hero itself:

  • Condition canUse before showing the skill button.
  • Action use when the player confirms.
  • onTick counts down; event ready when off cooldown.

6. Save as a prefab

  1. Select a fully configured enemy.
  2. Inspector → ActionsSave as Prefab.
  3. The prefab stores components, motion, and Object Flow graphs with field values.
  4. Spawning or placing from the library creates a new Thing with the same setup.

Tweak per-instance HP in the inspector after spawn; override dots appear when values differ from the prefab. Use Revert Prefab Overrides to reset.

See Prefabs for variants, subtree prefabs, and sync behavior.


7. Create a custom component (no code)

  1. Open the Components workspace (editor tab).
  2. Click + New.
  3. Set ID, label, category, description.
  4. Add fields (e.g. rage number 0–100).
  5. Add an action — choose Steps for visual blocks or Script for a short JS body.
  6. Save is automatic; the component is stored in the scene as a project component.

See Project components & Studio for the step language and Script API.


8. Play mode behavior

When you press Play:

  • ComponentHost.onPlayStart runs for each attachment (e.g. Health refills if configured).
  • onTick runs every frame for components that need it (Ability Cooldown, etc.).
  • Object Flow rules run as usual; component actions execute through the host.
  • On stop/reset, field values restore to the snapshot taken at play start.

Checklist

  • [ ] Enemy has Health + optional Health Bar + Stats + Combat Action + Team
  • [ ] Fighters share a Group name for Turn Queue
  • [ ] Controller has Turn Queue; graphs call rebuild / next
  • [ ] Object Flow uses component actions/conditions where possible
  • [ ] Prefabs used for repeated enemy types

Next: Built-in reference for every method and event, or Object Flow integration for expressions and Script nodes.

Opal Engine — MIT licensed