Writing Custom Effects (C#)
Other than using built-in effects or creating custom ones from the Inspector, you can easily program custom Effects via C#.
Effects have three key parts (which can be written in the same file).
Parameters class/struct
Contains information about the data/values you will use in your effect (state)
State struct
Main effect class. Given the parameters and a Character, modifies it through time. Also handles Modifiers
Scriptable Wrapper
Unifies the previous elements together and lets you save things on disk. A few of line of code to let us do the rest!
These names are just a convention, but you can call them however you prefer!
Just know that you need:
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
Writing your Custom Script
First, make sure to import the necessary namespaces (your IDE will tell you anyways <3)
using UnityEngine;
// import Text Animator's namespaces
using Febucci.TextAnimatorCore;
using Febucci.TextAnimatorCore.Text;
using Febucci.Parsing;
using Febucci.TextAnimatorForUnity.Effects;Parameters
Create the data you will need to modify the characters (it's the same one you will see and edit in the Inspector).
// 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.
// 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.
[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);
}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

Done! You’ve completed all the steps necessary, yay! The more effects you add, the more this process will sound familiar and simpler.
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
Have fun applying your effects!