Class ColorAnimationText
A runtime utility for computing animated color wave effects on multi-line text. Calculates per-line colors based on animation progress, gradient configurations, and directional flow - enabling smooth color animations for any text rendering system.
Inherited Members
Namespace: Scylla.Core.Util.Effects
Assembly: ScyllaCore.dll
Syntax
public sealed class ColorAnimationText
Remarks
This utility requires manual updates via the Update(float) method.
It does not update automatically and is decoupled from Unity's Time system.
Call Update(float) each frame, passing the elapsed delta time, to advance
the animation. This design allows independent time scaling per instance without
relying on UnityEngine.Time.
The gradient cycling system allows multiple ColorAnimationTextGradient instances to be registered via SetGradients(params ColorAnimationTextGradient[]) and automatically advanced on each loop completion when SetCycleGradients(bool) is enabled. This lets long-running infinite animations shift through entirely different color palettes over time without any external intervention.
All lifecycle methods return this, enabling a fluent configuration API:
<pre><code class="lang-csharp">var anim = ColorAnimationText.Create(4, ColorAnimationTextGradient.OceanBlues, 2f)
.SetDirection(ColorAnimationTextDirection.Down)
.SetLoops(-1)
.Start();</code></pre>
Constructors
ColorAnimationText(int, ColorAnimationTextGradient, float)
Initializes a new ColorAnimationText instance with the specified line count, gradient, and cycle duration.
Declaration
public ColorAnimationText(int lineCount, ColorAnimationTextGradient gradient, float cycleDuration = 1)
Parameters
| Type | Name | Description |
|---|---|---|
| int | lineCount | The number of text lines to animate. Must be at least |
| ColorAnimationTextGradient | gradient | The initial ColorAnimationTextGradient to use. Must not be |
| float | cycleDuration | The duration of one full animation cycle in seconds. Must be greater than |
Remarks
The following defaults are applied at construction:
- Direction - Down
- EaseType -
EaseType.Linear - LoopCount -
-1(infinite) - TimeScale -
1.0 - Gradient cycling - disabled
- IsRunning -
false(call Start() explicitly)
Shuffle offsets are generated automatically for all lines using
UnityEngine.Random.value. Call RegenerateShuffleOffsets() any
time to produce a different randomized distribution.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown if |
| ArgumentNullException | Thrown if |
Properties
CompletedLoops
Gets the number of completed animation cycles.
Declaration
public int CompletedLoops { get; }
Property Value
| Type | Description |
|---|---|
| int |
CurrentGradient
Gets the currently active ColorAnimationTextGradient used to compute per-line colors during each Update(float) call.
Declaration
public ColorAnimationTextGradient CurrentGradient { get; }
Property Value
| Type | Description |
|---|---|
| ColorAnimationTextGradient |
Remarks
The active gradient can be changed by calling SetGradient(ColorAnimationTextGradient) (replaces the entire gradient list with a single entry), SetGradients(params ColorAnimationTextGradient[]) (registers multiple gradients for cycling), NextGradient() (manually advances to the next gradient in the list), or SetGradientIndex(int) (jumps to a specific index). When gradient cycling is enabled via SetCycleGradients(bool), this property also changes automatically at the end of each completed loop. All changes fire OnGradientChanged.
CurrentGradientIndex
Gets the current gradient index.
Declaration
public int CurrentGradientIndex { get; }
Property Value
| Type | Description |
|---|---|
| int |
CycleDuration
Gets or sets the duration of one animation cycle in seconds. Must be greater than zero. Smaller values produce faster animations; larger values produce slower, smoother transitions.
Declaration
public float CycleDuration { get; set; }
Property Value
| Type | Description |
|---|---|
| float |
Remarks
The effective animation speed is the product of the cycle duration and TimeScale.
For example, a CycleDuration of 2.0 combined with a TimeScale of
0.5 results in an animation that completes one cycle every four seconds.
Changing this value mid-animation takes effect immediately on the next Update(float)
call without resetting progress.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown if value is less than or equal to zero. |
Direction
Gets or sets the direction of the color wave animation, controlling how colors flow across the text lines as the animation progresses.
Declaration
public ColorAnimationTextDirection Direction { get; set; }
Property Value
| Type | Description |
|---|---|
| ColorAnimationTextDirection |
Remarks
The available direction modes are:
- DownThe color wave flows from top to bottom; upper lines lead the wave.
- UpThe color wave flows from bottom to top; lower lines lead the wave.
- PingPongThe wave oscillates upward then downward repeatedly within each cycle.
- ShuffleEach line has a randomized phase offset, producing a scattered color pattern. Offsets are generated at construction and can be regenerated via RegenerateShuffleOffsets().
Changing this property takes effect immediately on the next GetLineColor(int) or GetAllLineColors() call without restarting the animation.
EaseType
Gets or sets the easing function applied to the raw Progress value before it is used to compute per-line gradient positions.
Declaration
public EaseType EaseType { get; set; }
Property Value
| Type | Description |
|---|---|
| EaseType |
Remarks
The easing transform is evaluated by Evaluate(EaseType, float)
on each color calculation. Using EaseType.Linear (the default) results in a
constant-speed color wave. Non-linear ease types such as EaseInOutSine create
acceleration and deceleration within each cycle, producing a pulsing or breathing feel.
Changing this property takes effect on the next color query without resetting progress.
GradientCount
Gets the number of gradients available for cycling.
Declaration
public int GradientCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
IsComplete
Gets a value indicating whether the animation has completed all configured loops.
Always returns false when LoopCount is -1 (infinite).
Declaration
public bool IsComplete { get; }
Property Value
| Type | Description |
|---|---|
| bool |
Remarks
When this returns true, IsRunning will also be false
and OnComplete will have fired. The only way to make an animation
eligible to complete is to set LoopCount to a non-negative value.
Calling Reset() or Restart() brings IsComplete
back to false by resetting CompletedLoops to zero.
IsPaused
Gets a value indicating whether the animation is currently paused.
Declaration
public bool IsPaused { get; }
Property Value
| Type | Description |
|---|---|
| bool |
IsRunning
Gets a value indicating whether the animation is currently running. An animation is running if it has been started and not stopped, even if paused.
Declaration
public bool IsRunning { get; }
Property Value
| Type | Description |
|---|---|
| bool |
LineCount
Gets the number of text lines being animated.
This value determines the valid range for GetLineColor(int) (0 to
LineCount - 1) and the required minimum size for the buffer passed to
GetAllLineColors(Color[]).
Declaration
public int LineCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
Remarks
The line count can be changed at runtime via SetLineCount(int) without restarting the animation. Increasing the count beyond the current value causes shuffle offsets to be automatically regenerated for all lines.
LoopCount
Gets or sets the maximum number of animation cycles to run before the animation
stops automatically. Set to -1 for infinite looping. Default is -1.
Declaration
public int LoopCount { get; set; }
Property Value
| Type | Description |
|---|---|
| int |
Remarks
This is a ceiling, not a counter. To read how many cycles have already completed,
use CompletedLoops. The animation stops and OnComplete
fires as soon as CompletedLoops >= LoopCount (for non-negative values).
When set to -1, IsComplete always returns false and
OnComplete is never fired. This value can be changed at runtime
without restarting the animation.
Progress
Gets the current animation progress as a normalized value in the range [0, 1).
A value of 0 represents the start of a cycle; a value approaching 1
represents the end just before the next loop begins.
Declaration
public float Progress { get; }
Property Value
| Type | Description |
|---|---|
| float |
Remarks
This is the raw progress before any easing is applied. The actual position
used for color calculations is derived from this value after it is passed through the
function specified by EaseType. Progress resets to 0 on each
completed loop and when Start(), Restart(), or
Reset() is called.
TimeScale
Gets or sets the time scale multiplier applied to the delta time passed to
Update(float). Use values less than 1 for slow motion and values
greater than 1 for fast-forward. Default is 1.0.
Declaration
public float TimeScale { get; set; }
Property Value
| Type | Description |
|---|---|
| float |
Remarks
Setting TimeScale to 0 effectively freezes the animation without
going through the Pause() / Resume() path and without
changing IsPaused. This is useful for transient freezes driven by
game state rather than explicit pause requests.
Negative values reverse the direction of progress accumulation, causing the
animation to run backwards. Note that loop-completion logic still triggers when
Progress exceeds 1, so combined with a wrapping gradient
the visual result will be a reversed color wave.
Exceptions
| Type | Condition |
|---|---|
| ArgumentException | Thrown when value is NaN or Infinity. |
Methods
Create(int, ColorAnimationTextGradient, float)
Creates and returns a new ColorAnimationText instance with the specified parameters. Equivalent to calling the constructor directly, but enables use in fluent initialization chains without a separate variable declaration.
Declaration
public static ColorAnimationText Create(int lineCount, ColorAnimationTextGradient gradient, float cycleDuration = 1)
Parameters
| Type | Name | Description |
|---|---|---|
| int | lineCount | The number of text lines to animate. Must be at least |
| ColorAnimationTextGradient | gradient | The initial ColorAnimationTextGradient to use. Must not be |
| float | cycleDuration | The duration of one animation cycle in seconds. Must be greater than |
Returns
| Type | Description |
|---|---|
| ColorAnimationText | A fully initialized ColorAnimationText instance, not yet running. |
Remarks
Example of a complete fluent setup:
var anim = ColorAnimationText.Create(6, ColorAnimationTextGradient.RoyalPurples, 1.5f)
.SetDirection(ColorAnimationTextDirection.PingPong)
.SetEase(EaseType.InOutSine)
.SetLoops(3)
.Start();
GetAllLineColors()
Returns a new Color array containing the current animated color for every
text line, from index 0 to LineCount - 1.
Declaration
public Color[] GetAllLineColors()
Returns
| Type | Description |
|---|---|
| Color[] | A newly allocated |
Remarks
This overload allocates a new array on every call. For hot paths or tight render loops where garbage pressure matters, use the buffer overload GetAllLineColors(Color[]) instead to write results into a pre-allocated array without any allocation.
GetAllLineColors(Color[])
Writes the current animated color for every text line into the provided buffer, avoiding any heap allocation. Suitable for use in render-loop hot paths.
Declaration
public void GetAllLineColors(Color[] buffer)
Parameters
| Type | Name | Description |
|---|---|---|
| Color[] | buffer | The pre-allocated |
Remarks
This overload performs zero heap allocations. Allocate the buffer once (e.g., in
Awake or alongside the animation instance) and reuse it each frame. The
allocating overload GetAllLineColors() is more convenient when
allocation cost is not a concern.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown if |
| ArgumentException | Thrown if |
GetLineColor(int)
Returns the current animated color for the specified text line, computed from the current Progress, Direction, EaseType, and CurrentGradient.
Declaration
public Color GetLineColor(int lineIndex)
Parameters
| Type | Name | Description |
|---|---|---|
| int | lineIndex | The zero-based index of the text line. Must be in the range
|
Returns
| Type | Description |
|---|---|
| Color | The interpolated |
Remarks
This method queries the color at the current animation snapshot. The returned color is stable between Update(float) calls - calling it multiple times in a frame for the same index will yield the same result. For retrieving all line colors in a single pass, prefer GetAllLineColors() or the zero-allocation overload GetAllLineColors(Color[]).
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown if |
NextGradient()
Advances the active gradient to the next entry in the gradient list, wrapping back
to index 0 after the last entry. Fires OnGradientChanged.
Declaration
public ColorAnimationText NextGradient()
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance, to support method chaining. |
Remarks
When only a single gradient is registered, this method is a no-op: it returns immediately without changing the active gradient or firing any event. To add multiple gradients, call SetGradients(params ColorAnimationTextGradient[]) first.
Pause()
Pauses the animation, preserving the current progress. Has no effect if the animation is not running.
Declaration
public ColorAnimationText Pause()
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance for method chaining. |
RegenerateShuffleOffsets()
Regenerates the randomized per-line phase offsets that are used exclusively in Shuffle mode, producing a new distribution of colors across lines.
Declaration
public ColorAnimationText RegenerateShuffleOffsets()
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance, to support method chaining. |
Remarks
Each offset is independently sampled from UnityEngine.Random.value, yielding
values in the range [0, 1). The offsets are generated once at construction and
can be refreshed at any time via this method - for example, on each new game round or
scene load - without restarting the animation. This method has no visible effect when
the current Direction is not Shuffle.
Reset()
Resets the animation to its initial state: stops it, sets Progress
and CompletedLoops to zero, and resets the active gradient to the
first entry in the gradient list (index 0).
Declaration
public ColorAnimationText Reset()
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance, to support method chaining. |
Remarks
After calling Reset, IsRunning is false and no events
are fired. To start the animation again from a clean state, call Start()
or use Restart() to perform both steps atomically (though
Restart() does not reset the gradient index).
Restart()
Restarts the animation from the beginning without an intermediate stopped state.
Functionally equivalent to calling Reset() followed by Start(),
but the transition is atomic - IsRunning never briefly becomes
false between the reset and the start.
Declaration
public ColorAnimationText Restart()
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance, to support method chaining. |
Remarks
Unlike Reset(), Restart does not reset the gradient index.
The animation continues from whichever gradient is currently active. If you need the
gradient index reset to 0 as well, call Reset() then
Start() separately.
Resume()
Resumes a paused animation from where it left off. Has no effect if the animation is not paused.
Declaration
public ColorAnimationText Resume()
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance for method chaining. |
SetCycleDuration(float)
Sets the duration of one animation cycle.
Declaration
public ColorAnimationText SetCycleDuration(float duration)
Parameters
| Type | Name | Description |
|---|---|---|
| float | duration | The cycle duration in seconds. |
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance for method chaining. |
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown if duration is less than or equal to zero. |
SetCycleGradients(bool)
Enables or disables automatic gradient cycling on each loop completion.
Declaration
public ColorAnimationText SetCycleGradients(bool cycle)
Parameters
| Type | Name | Description |
|---|---|---|
| bool | cycle |
|
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance, to support method chaining. |
Remarks
When enabled, the gradient advances at the same point in the Update(float) loop where OnGradientChanged fires - before OnCycleComplete. Cycling only occurs when more than one gradient has been registered via SetGradients(params ColorAnimationTextGradient[]). If only a single gradient exists the flag is stored but has no visible effect until additional gradients are added.
SetDirection(ColorAnimationTextDirection)
Sets the direction of the color wave animation.
Declaration
public ColorAnimationText SetDirection(ColorAnimationTextDirection direction)
Parameters
| Type | Name | Description |
|---|---|---|
| ColorAnimationTextDirection | direction | The animation direction. |
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance for method chaining. |
SetEase(EaseType)
Sets the easing type for the animation.
Declaration
public ColorAnimationText SetEase(EaseType easeType)
Parameters
| Type | Name | Description |
|---|---|---|
| EaseType | easeType | The easing type. |
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance for method chaining. |
SetGradient(ColorAnimationTextGradient)
Replaces the current gradient list with a single ColorAnimationTextGradient and sets it as the active gradient. Fires OnGradientChanged.
Declaration
public ColorAnimationText SetGradient(ColorAnimationTextGradient gradient)
Parameters
| Type | Name | Description |
|---|---|---|
| ColorAnimationTextGradient | gradient | The ColorAnimationTextGradient to use. Must not be |
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance, to support method chaining. |
Remarks
This method discards all previously registered gradients (including any registered
via SetGradients(params ColorAnimationTextGradient[])) and replaces them with the single provided
gradient. The gradient index resets to 0. If you want to keep multiple
gradients available for cycling, use SetGradients(params ColorAnimationTextGradient[]) instead.
OnGradientChanged is always fired, even if the provided gradient
is the same instance as the current one.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown if |
SetGradientIndex(int)
Sets the active gradient to the entry at the specified index within the gradient list. Fires OnGradientChanged only if the index changes.
Declaration
public ColorAnimationText SetGradientIndex(int index)
Parameters
| Type | Name | Description |
|---|---|---|
| int | index | The zero-based index of the gradient to activate. Must be in the range
|
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance, to support method chaining. |
Remarks
If index equals the current CurrentGradientIndex,
this method is effectively a no-op: the active gradient is unchanged and
OnGradientChanged is not fired. This conditional behavior avoids
spurious event notifications when the desired gradient is already active.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown if |
SetGradients(params ColorAnimationTextGradient[])
Registers an ordered list of ColorAnimationTextGradient instances
for cycling during animation, resets the active gradient to index 0, and
fires OnGradientChanged.
Declaration
public ColorAnimationText SetGradients(params ColorAnimationTextGradient[] gradients)
Parameters
| Type | Name | Description |
|---|---|---|
| ColorAnimationTextGradient[] | gradients | One or more ColorAnimationTextGradient instances. Must not be
|
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance, to support method chaining. |
Remarks
A defensive copy of the array is made internally, so subsequent modifications to the
passed array will not affect the animation. The gradient index is always reset to
0, making the first element of gradients the active
gradient immediately. To enable automatic advancement through the list on each loop
completion, call SetCycleGradients(bool) with true after this method.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown if |
| ArgumentException | Thrown if |
SetLineCount(int)
Sets the number of text lines to animate. Can be called at runtime without restarting the animation.
Declaration
public ColorAnimationText SetLineCount(int count)
Parameters
| Type | Name | Description |
|---|---|---|
| int | count | The new number of lines. Must be at least |
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance, to support method chaining. |
Remarks
If count exceeds the current size of the internal shuffle
offset array, a new array is allocated and all offsets are regenerated via
UnityEngine.Random.value. If the count decreases or stays the same, the
existing offsets are reused (no reallocation occurs). The animation continues
uninterrupted from its current Progress.
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown if |
SetLoops(int)
Sets the maximum number of animation loops.
Declaration
public ColorAnimationText SetLoops(int loops)
Parameters
| Type | Name | Description |
|---|---|---|
| int | loops | The number of loops. Use -1 for infinite looping. |
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance for method chaining. |
SetTimeScale(float)
Sets the time scale multiplier.
Declaration
public ColorAnimationText SetTimeScale(float scale)
Parameters
| Type | Name | Description |
|---|---|---|
| float | scale | The time scale multiplier. |
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance for method chaining. |
Start()
Starts the animation from the beginning, resetting progress and the completed loop counter to zero. If the animation was previously paused or stopped, it will run from the start regardless of its prior state.
Declaration
public ColorAnimationText Start()
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance, to support method chaining. |
Remarks
Before returning, Start sets Progress to 0,
CompletedLoops to 0, IsRunning to true,
and IsPaused to false, then fires OnStart.
Unlike Resume(), which continues from where the animation was paused,
Start always rewinds to the very beginning of the first cycle.
Stop()
Stops the animation completely, setting IsRunning to false.
The current Progress and CompletedLoops values are
preserved; the animation position is not reset.
Declaration
public ColorAnimationText Stop()
Returns
| Type | Description |
|---|---|
| ColorAnimationText | This instance, to support method chaining. |
Remarks
To discard the current position entirely, call Reset() instead.
Calling Start() after Stop will restart from the beginning
regardless, since Start always resets progress.
Update(float)
Advances the animation by the specified elapsed time. Must be called every frame (or on any tick) to drive the animation forward; the class performs no automatic updating.
Declaration
public void Update(float deltaTime)
Parameters
| Type | Name | Description |
|---|---|---|
| float | deltaTime | The time elapsed since the last update call, in seconds. Typically
|
Remarks
The method returns immediately if IsRunning is false or
IsPaused is true. It also short-circuits if
IsComplete is already true at the time of the call, which
guards against over-running a completed finite animation.
When a cycle boundary is crossed (progress reaches or exceeds 1.0), the
following actions happen in order for each completed cycle:
- Progress wraps by subtracting
1.0and CompletedLoops increments. - If gradient cycling is enabled and multiple gradients exist, the gradient index advances and OnGradientChanged fires.
- OnCycleComplete fires.
- If LoopCount is non-negative and CompletedLoops has reached it, progress resets to
0, IsRunning is set tofalse, OnComplete fires, and the method returns.
Events
OnComplete
Invoked once when the animation has completed all configured loops and stops.
Never invoked when LoopCount is -1 (infinite).
Declaration
public event Action OnComplete
Event Type
| Type | Description |
|---|---|
| Action |
Remarks
This event fires after OnCycleComplete for the final cycle, at
which point Progress has been reset to 0 and
IsRunning has been set to false. It fires at most once per
Start() or Restart() call. To run the animation again
after completion, call Start() or Restart() from inside
this handler or from calling code.
OnCycleComplete
Invoked each time an animation cycle completes (i.e., Progress
reaches or exceeds 1.0).
Declaration
public event Action OnCycleComplete
Event Type
| Type | Description |
|---|---|
| Action |
Remarks
Within a single Update(float) call, this event fires after any automatic gradient advance (when cycle-gradient mode is enabled) and before the OnComplete check. In the rare case that the elapsed delta time is large enough to span multiple cycles, this event fires once per completed cycle in the order they occurred. It is safe to modify LoopCount or CycleDuration inside a handler.
OnGradientChanged
Invoked whenever the active CurrentGradient changes to a different ColorAnimationTextGradient instance.
Declaration
public event Action OnGradientChanged
Event Type
| Type | Description |
|---|---|
| Action |
Remarks
This event fires from the following sources:
- SetGradient(ColorAnimationTextGradient) - replaces all gradients with a single entry.
- SetGradients(params ColorAnimationTextGradient[]) - registers a new gradient list and resets to index 0.
- NextGradient() - manually advances to the next gradient in the list.
- SetGradientIndex(int) - jumps to a specific gradient index (only fires when the index changes).
- Update(float) - fires automatically on each cycle completion when gradient cycling is enabled via SetCycleGradients(bool).
The event does not fire when SetGradientIndex(int) is called with the same index that is already active.
OnStart
Invoked when the animation begins or restarts from the beginning.
Declaration
public event Action OnStart
Event Type
| Type | Description |
|---|---|
| Action |
Remarks
This event fires at the end of both Start() and Restart(),
after progress and completed loop counts have been reset to zero and
IsRunning has been set to true. It does not fire on
Resume(), which continues from a paused state rather than restarting.
Any exceptions thrown by subscribers are caught and logged via
UnityEngine.Debug.LogException, so a failing subscriber does not prevent
other subscribers from executing.