# Writing Custom Effects (C#)

Other than using [built-in effects](/text-animator-unity/effects/built-in-effects-list.md) or [creating custom ones from the Inspector](/text-animator-unity/customization/create-your-own-effects.md), <mark style="background-color:$warning;">**you can easily program custom Effects via C#**</mark>.

{% hint style="info" %}
P.S. Make sure you have read the [Advanced Concepts](/text-animator-unity/writing-custom-classes/advanced-concepts.md) page!
{% endhint %}

Effects have three key parts (which can be written in the same file).

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Parameters class/struct</strong></td><td>Contains information about the data/values you will use in your effect (<strong>state)</strong> </td></tr><tr><td><strong>State</strong> struct</td><td>Main effect class. Given the parameters and a Character, modifies it through time. Also handles <a data-mention href="/pages/Uy9gvp1wChJrN5imt9Ho">/pages/Uy9gvp1wChJrN5imt9Ho</a></td></tr><tr><td><strong>Scriptable Wrapper</strong></td><td>Unifies the previous elements together and lets you save things on disk. A few of line of code to let us do the rest!</td></tr></tbody></table>

{% hint style="success" %}
These names are just a convention, but **you can call them however you prefer**!

Just know that you need:&#x20;

* Something that stores effect variables
* A struct responsible for modifying letters
* The Scriptable that glues these two togheter and lets you save the info on disk
  {% endhint %}

## Writing your Custom Script

{% hint style="info" %}
For this example, we're making an effect that makes a character go up by a variable amount.
{% endhint %}

First, make sure to import the necessary namespaces (your IDE will tell you anyways <3)

<pre class="language-csharp"><code class="lang-csharp">using UnityEngine;

// import Text Animator's namespaces
<strong>using Febucci.TextAnimatorCore;
</strong>using Febucci.TextAnimatorCore.Text;
<strong>using Febucci.Parsing;
</strong><strong>using Febucci.TextAnimatorForUnity.Effects;
</strong></code></pre>

### Parameters

Create the data you will need to modify the characters (it's the same one you will see and edit in the Inspector).

```csharp
// can be either struct or class
// the latter allows you to have default values
[System.Serializable]
class CustomEffectParameters
{
    public float amount = 1.5f;
}
```

### State

The "core" part of an effect. Modifies the letter given the parameters and pre-calculated Text Animator data.

* The struct must inherit from **IEffectState**.

```csharp
// must be struct!
struct CustomEffectState : IEffectState
{
    readonly float defaultAmount;
    float amount;


    public CustomEffectState(CustomEffectParameters data)
    {
        // gets the default amount from the parameters class
        this.defaultAmount = data.amount;
        this.amount = defaultAmount;
    }

    public void UpdateParameters(RegionParameters parameters)
    {
        // automatically handles cases where the user wrote 
        // modifiers in the rich text tag, "a" in this case
        // (e.g. <tagID a=5> will set "amount" to 5, while 
        // a*2 will make "amount" two times defaultAmount)
        amount = parameters.ModifyFloat("a", defaultAmount);
    }

    public void Apply(ref CharacterData character, in ManagedEffectContext context)
    {
        // uses "amount" to move the character up
        // with a clear and easy to use API
        character.MovePosition(
            Vector3.Up * amount * context.progressionRange * context.intensity,
            context.isUpPositive
            );
        // 1. note context.progressionRange -> it's the 
        //     curve you have assigned in the editor!
        //     allowing you for a step, a sine, bounce etc. result
        // 2. note also the context.intensity, needed to have 
        //     smooth transitions between stages.
        }
}
```

### Scriptable Object Wrapper

Creates the logic necessary to hook your custom effect into Text Animator, also saving it in the Assets folder.

```csharp
[System.Serializable] // <-- make it serializable!!
[CreateAssetMenu(fileName = "Your Custom Effect")]
class CustomEffectScriptable : ManagedEffectScriptable<CustomEffectState, CustomEffectParameters>
{
    // simply creates a new State, given the Parameters (already managed by text animator)
    protected override CustomEffectState CreateState(CustomEffectParameters parameters)
        => new CustomEffectState(parameters);
}
```

{% hint style="info" %}
There is another version of "ManagedEffectScriptable" which accepts more types, as well as the "Referenced" effect implementation, but we will cover than from future versions!
{% endhint %}

{% hint style="success" %}
These scripts are all Text Animator needs to make sure you get:

* Auto-managed curves, playbacks, modifiers
* Optimized effects without race conditions
* Compatible effects in AOT platforms (without the need to use Reflection)
* Our powerful preview editor
* Effects that work the same on UI Toolkit and Text Mesh Pro, including dynamic scaling

and more! <3
{% endhint %}

<figure><img src="/files/IalLJbrPSftYWC1fh9TH" alt=""><figcaption></figcaption></figure>

***

{% hint style="success" %}
Done!  **You’ve completed all the steps necessary, yay!**\
The more effects you add, the more this process will sound familiar and simpler.
{% endhint %}

{% hint style="warning" %}
Remember to give your effect a tag (from the inspector) and to add it to the database! Otherwise it will not be recognized. You can read more here: [Effects Database](/text-animator-unity/effects/how-to-add-effects/effects-database.md)
{% endhint %}

**Have fun applying your effects!**

***

{% hint style="info" %}
A guide for creating "Referenced" effects is coming soon, as we're still tinkering the UX/API part.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.febucci.com/text-animator-unity/writing-custom-classes/writing-custom-effects-c.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
