> For the complete documentation index, see [llms.txt](https://docs.perception.cx/perception/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.perception.cx/perception/lua-script/life-cycle.md).

# Life Cycle

Every Lua script **must define** an entry function:

***

#### **main()**

```lua
function main()
    ...
    return number
end
```

| Return Value | Meaning                                              |
| ------------ | ---------------------------------------------------- |
| **> 0**      | Script stays active **only if** `on_frame()` exists. |
| **≤ 0**      | Script unloads immediately after `main()` finishes.  |

***

#### **on\_frame()**

```lua
function on_frame()
    ...
end
```

| Behavior    | Meaning                                                        |
| ----------- | -------------------------------------------------------------- |
| **Missing** | Script unloads right after `main()` (even if it returned > 0). |
| **Exists**  | Runs every frame. Returning **≤ 0** unloads the script.        |

***

### on\_unload()

```lua
function on_unload()
    ...
end
```

* Called once **when the script is about to be unloaded**.
* Use this to clean up state, save data, etc.
* Cannot prevent the script from unloading

***

### ◆ Execution Flow

1. The engine runs the script’s `main()` function.
2. After `main()` returns:
   * If return value **≤ 0** → script unloads.
   * If return value **> 0**:
     * If `on_frame()` exists → script becomes persistent.
     * If `on_frame()` is missing → script unloads immediately.
3. For persistent scripts, `on_frame()` runs every frame until:
   * It returns **≤ 0**, or
   * The script is manually unloaded.
4. When the script is unloading, `on_unload()` is called once (if defined)

***

### ◆ Example #1 — Persistent Script

```lua
function main()
    log("Persistent script.")
    return 1
end

function on_frame()
    log("Tick")
end
```

***

### ◆ Example #2 — One-shot Script

```lua
function main()
    log("This runs once.")
    return 1   -- still unloads because on_frame() is missing
end
```

***

### ◆ Engine Notes

* `main()` is **required**.
* `on_frame()` is **optional**, but required for a script to stay active.
* Returning **≤ 0** from either function unloads the script.
* No infinite loops — frame updates are handled by the engine.
