# Writing Custom Effects (C#)

Other than using [built-in effects](https://docs.febucci.com/text-animator-unity/effects/built-in-effects-list) or [creating custom ones from the Inspector](https://docs.febucci.com/text-animator-unity/customization/create-your-own-effects), <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](https://docs.febucci.com/text-animator-unity/writing-custom-classes/advanced-concepts "mention") 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="../effects/how-to-edit-effects/modifiers">modifiers</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="https://3857371675-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXuXUTa2X5PYuYL6yRvl1%2Fuploads%2FpaXEW0rl1anhoSBUK719%2FClipboard-20251116-235502-613.gif?alt=media&#x26;token=72885c85-f75f-43db-969c-ab4a72c28803" 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](https://docs.febucci.com/text-animator-unity/effects/how-to-add-effects/effects-database "mention")
{% 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 %}
