> For the complete documentation index, see [llms.txt](https://docs.overdare.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.overdare.com/manual/studio-manual/object/vfx/vfxrecipe.md).

# VFXRecipe

## Overview

VFXRecipe is an object that lets you combine multiple VFX sources in a layered structure to build a composite effect and control its playback through scripts.

Whereas VFXPreset lets you choose from predefined effects, VFXRecipe lets you compose an effect yourself by placing VFX sources directly on three layers—Base, Detail, and Extra. Parameters such as each source's color, size, and transparency can be controlled at runtime through scripts, enabling a wide range of visual variations.

## How to Use

### Placing a VFXRecipe

<figure><img src="https://2064130887-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhrvYlLq1mQAq0V0vwPsb%2Fuploads%2Fgit-blob-c55d8f1ba9d9b41e7dcb5e3b738b0a386493eb58%2Fimage%20(768).png?alt=media" alt=""><figcaption></figcaption></figure>

Place a VFXRecipe at the desired location in the Level Browser.

Select the placed VFXRecipe to edit its layer composition and playback settings in the property panel.

### Layer Composition

A VFXRecipe has three layers: Base, Detail, and Extra.

<table><thead><tr><th width="140">Layer</th><th>Role</th></tr></thead><tbody><tr><td>BaseLayer</td><td>Responsible for the core visual elements of the effect. At least one source must be placed here.</td></tr><tr><td>DetailLayer</td><td>Adds finer details on top of the BaseLayer. Placement is optional.</td></tr><tr><td>ExtraLayer</td><td>Adds supplementary auxiliary effects. Placement is optional.</td></tr></tbody></table>

Click the + button on each layer to add a source. In the added source entry, click the VFX Source field to select a VFX source asset, and enter a name in the Name field. The name is used to identify the source when controlling parameters with `GetParam` / `SetParam` in scripts.

<figure><img src="https://2064130887-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhrvYlLq1mQAq0V0vwPsb%2Fuploads%2Fgit-blob-c17de7c8eaa64f04b40f134257d37d9ed498b988%2Fimage%20(769).png?alt=media" alt=""><figcaption></figcaption></figure>

### Playback Settings

| Property     | Description                                                                                                                                                                   |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| AutoActivate | If `true`, playback starts automatically when the instance is activated. The default value is `true`.                                                                         |
| InfiniteLoop | If `true`, the effect loops infinitely until `Stop()` is called. The default value is `false`.                                                                                |
| LoopCount    | The number of playback repetitions. Applied only when InfiniteLoop is `false`. The default value is `1`.                                                                      |
| LoopDuration | The duration (in seconds) of a single playback, calculated automatically by analyzing the parameters of the sources registered to the layers. It cannot be modified directly. |

## Controlling with Scripts

### Play and Stop

Control effect playback manually with `Play()` and `Stop()`. When called from a server script, playback is automatically synchronized to all clients.

```lua
local vfxRecipe = script.Parent

-- Disable auto play, then play manually after 2 seconds
vfxRecipe.AutoActivate = false
wait(2)
vfxRecipe:Play()

wait(3)
vfxRecipe:Stop()
```

### Detecting Playback Completion

When InfiniteLoop is `false` and playback finishes LoopCount times, the `Finished` event fires. It does not fire when playback is forcibly stopped with `Stop()`.

```lua
local vfxRecipe = script.Parent

vfxRecipe.InfiniteLoop = false
vfxRecipe.LoopCount = 3

vfxRecipe.Finished:Connect(function()
    print("Playback finished.")
end)

vfxRecipe:Play()
```

### Controlling Parameters

Use `SetParam(SourceName, ParamName, Value)` to change a source's parameters at runtime. Passing an empty string (`""`) as SourceName applies the change to every source on every layer at once.

```lua
local vfxRecipe = script.Parent

-- Change the size of a specific source
vfxRecipe:SetParam("FlameSource", "Size", 2)

-- Change the transparency of all sources at once
vfxRecipe:SetParam("", "Transparency", 0.5)

-- Change the color with a ColorSequence
local colorKeys = {
    ColorSequenceKeypoint.new(0, Color3.fromRGB(255, 100, 0)),
    ColorSequenceKeypoint.new(1, Color3.fromRGB(255, 220, 0)),
}
vfxRecipe:SetParam("FlameSource", "Color", ColorSequence.new(colorKeys))
```

Use `GetParam(SourceName, ParamName)` to read the current parameter value.

```lua
local vfxRecipe = script.Parent

local currentSize = vfxRecipe:GetParam("FlameSource", "Size")
print("Current size:", currentSize)
```

To specify a source by layer name and index instead of the source name, use `SetParamAt` / `GetParamAt`. Indexes start at 0.

```lua
local vfxRecipe = script.Parent

-- Change the size of the first source on the Base layer
vfxRecipe:SetParamAt("Base", 0, "Size", 1.5)

-- Get the transparency of the second source on the Detail layer
local transparency = vfxRecipe:GetParamAt("Detail", 1, "Transparency")
print("Transparency:", transparency)
```

### Parameters Modifiable at Runtime

The parameters that can be changed at runtime with `SetParam` depend on the source's SpawnType.

<table><thead><tr><th width="160">Parameter</th><th width="100">SpawnType</th><th>Description</th></tr></thead><tbody><tr><td>Size</td><td>Common</td><td>Particle size scale</td></tr><tr><td>Color</td><td>Common</td><td>Particle color (ColorSequence)</td></tr><tr><td>Transparency</td><td>Common</td><td>Particle opacity (0–1)</td></tr><tr><td>Offset</td><td>Common</td><td>Particle spawn position offset (Vector3)</td></tr><tr><td>SpawnCount</td><td>burst</td><td>Number of particles spawned at once on activation</td></tr><tr><td>SpawnRate</td><td>rate</td><td>Number of particles spawned per second</td></tr><tr><td>Speed</td><td>rate</td><td>Particle movement speed (0–100)</td></tr><tr><td>BoundSize</td><td>rate</td><td>Size of the particle spawn area</td></tr><tr><td>Duration</td><td>rate</td><td>Emitter duration (seconds)</td></tr></tbody></table>

{% hint style="warning" %}
`LoopCount` is not a source parameter. Set it with `vfxRecipe.LoopCount = N`.
{% endhint %}

### Complete Example

This example plays an effect, changes its color and size during playback, and restores the original values when playback finishes.

```lua
local vfxRecipe = script.Parent

local function playWithEffect()
    -- Set parameters before playback
    vfxRecipe:SetParam("", "Size", 2)
    vfxRecipe:SetParam("", "Color", ColorSequence.new(Color3.fromRGB(0, 150, 255)))

    vfxRecipe.InfiniteLoop = false
    vfxRecipe.LoopCount = 2

    -- Restore original values when playback finishes
    local conn
    conn = vfxRecipe.Finished:Connect(function()
        conn:Disconnect()
        vfxRecipe:SetParam("", "Size", 1)
        vfxRecipe:SetParam("", "Color", ColorSequence.new(Color3.fromRGB(255, 100, 0)))
    end)

    vfxRecipe:Play()
end

playWithEffect()
```

## Scripting

{% content-ref url="/pages/dRrAyIlsFe1CWBZXQbes" %}
[VFXRecipe](/development/api-reference/classes/vfxrecipe.md)
{% endcontent-ref %}
