# <pc-script-instance>

The `<pc-script-instance>` tag attaches one script to the entity of its parent [`<pc-script>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-script.md): an instance of the script class that its `name` names, configured by its other attributes.

:::note[Usage]

* It must be a direct child of a [`<pc-script>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-script.md) component.
* Its script class is registered by loading the script's module with a [`<pc-asset>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-asset.md) tag, or by calling `registerScript()` from your own code once `<pc-app>` is ready.

:::

## Attributes

| Attribute | Type | Default | Description |
| --- | --- | --- | --- |
| `attributes` | String | - | JSON object of script attributes. Use it for nested structures and for script attribute names that collide with reserved HTML attribute names (e.g. `title`) |
| `enabled` | Boolean | `"true"` | Enabled state of the script |
| `name` | String | - | Name the script class is registered under: its `scriptName` property, or the name passed to `registerScript()` |

In addition, any other non-reserved attribute maps to the script attribute of the same name (kebab-case to camelCase, e.g. `focus-point` → `focusPoint`). Values are parsed according to the type of the script's declared default, and the `asset:`/`entity:`/`vec2:`/`vec3:`/`vec4:`/`color:` prefixes can be used where inference cannot help. An `entity:` value is an entity `name` — write `entity:#id` to reference an element by `id`. If the same script attribute is also present in the `attributes` JSON, the per-property attribute wins. See [Adding Behavior with Scripts](https://developer.playcanvas.com/user-manual/web-components/scripting.md) for full details.

Declared values are the source of truth. A script instance can outlive a reload of what its entity holds — a [`<pc-model>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-model.md) keeps its host entity, and the scripts on it, when its `asset` changes — and a surviving instance has its declared state re-asserted, which deliberately snaps back any runtime mutation of a declared property. Keep state you change at runtime in properties the markup does not declare. A [`<pc-node>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-node.md) that rebinds is a different case: it binds a new entity, so its scripts are created afresh.

The script class does not have to be registered before the element is added. An element whose class is not registered yet waits for it, and once the class arrives the instance is created as usual, with every declared attribute applied before `initialize()` runs. If the class is still missing once no script asset is left loading, the console warns that the element is waiting and asks whether its `<pc-asset>` is missing — the usual causes are a forgotten `<pc-asset>` and a `name` that does not match the script's `scriptName`. The element keeps waiting either way, so a class registered later still gets its instance.

## Events

Listen to these events using [`addEventListener()`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener).

| Event | Description |
| --- | --- |
| `scriptattributeschange` | Fired when the `attributes` JSON or the `scriptAttributes` property is set. `detail.attributes` carries the new attributes object. Per-property attributes do not fire it. |
| `scriptenablechange` | Fired whenever `enabled` is set, even to the value it already had. `detail.enabled` carries the new state. |
| `scriptnamechange` | Fired when the script is renamed by changing `name` on an element that already had one. `detail.oldName` and `detail.newName` carry the two names, and the parent [`<pc-script>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-script.md) responds by destroying the old script and creating the new one. |

All three bubble. The parent [`<pc-script>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-script.md) listens for them to apply each change to the engine, and the same events let your own code observe those changes — one listener on an ancestor covers every script instance beneath it. The parent picks up per-property attribute changes by watching the elements themselves, so to observe those, use a [`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).

## Example

A `rotate` script attached to a cube. Script classes usually load from a [`<pc-asset>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-asset.md), but they can also be registered from an inline module — the `<pc-script-instance>` stays pending until its class arrives. Try changing the rotation rates:

```html live-example
<pc-app>
    <pc-scene>
        <pc-entity name="camera" position="0 0 3">
            <pc-camera clear-color="#1d1f2b"></pc-camera>
        </pc-entity>
        <pc-entity name="light" rotation="45 30 0">
            <pc-light></pc-light>
        </pc-entity>
        <pc-entity name="cube">
            <pc-render type="box"></pc-render>
            <pc-script>
                <pc-script-instance name="rotate"></pc-script-instance>
            </pc-script>
        </pc-entity>
    </pc-scene>
</pc-app>
<script type="module">
    import { registerScript, Script } from 'playcanvas';
    import { whenReady } from '@playcanvas/web-components';

    // Wait for the application, then register the script class
    await whenReady('pc-app');

    class Rotate extends Script {
        update(dt) {
            this.entity.rotate(10 * dt, 20 * dt, 30 * dt);
        }
    }

    registerScript(Rotate, 'rotate');
</script>
```

## JavaScript Interface

You can programmatically create and manipulate `<pc-script-instance>` elements using the [ScriptInstanceElement API](https://api.playcanvas.com/web-components/classes/ScriptInstanceElement.html).

The element becomes ready once its script instance has been created — await `whenReady('pc-script-instance')` or the element's `ready()` promise. The live `Script` instance is then available via the `script` property, and script attributes can be set as an object via the `scriptAttributes` property, the same channel as the `attributes` JSON.

## See Also

* [`<pc-script>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-script.md) — the component that hosts instances
* [`<pc-asset>`](https://developer.playcanvas.com/user-manual/web-components/tags/pc-asset.md) — loads the script's module
* [Adding Behavior with Scripts](https://developer.playcanvas.com/user-manual/web-components/scripting.md) — declaring and typing script attributes

Examples: [Tweening](https://playcanvas.github.io/web-components/examples/#tweening.html), [Solar System](https://playcanvas.github.io/web-components/examples/#solar-system.html) and [Annotations](https://playcanvas.github.io/web-components/examples/#annotations.html).
