# 💻 7. Runtime Control (C# ECS API)

While the GPU handles the heavy lifting of rendering the animations, your game logic (running on the CPU via ECS Systems) needs to tell the characters what to do. Should they run, attack, or die?

**GPU Animation Entities PRO** provides a clean, allocation-free C# API to control your units using standard DOTS `IComponentData` and `DynamicBuffer` components.

***

#### 🗂️ The Generated Parameters Class

In traditional Unity, you trigger animations using strings (e.g., `animator.SetFloat("Speed", 1.0f)`). In DOTS, strings are slow and cause memory allocations.

To solve this, whenever you bake a prefab, our Baker automatically generates a static C# script containing byte IDs for all your animations and parameters.

You can find this file in your project at:\
`Assets/SnivelerCode/GpuAnimation/Generated/[YourPrefabName]/Scripts/GeneratedParams.cs`

It looks something like this:

```csharp
namespace SnivelerCode.GpuAnimation.Generated
{
    // Animation State IDs
    public static class AnimatorGuardCastle
    {
        public static readonly byte Idle = 0;
        public static readonly byte Run = 1;
        public static readonly byte Attack = 2;
    }

    // Parameter IDs
    public static partial class AnimatorParams
    {
        public static class GuardCastle
        {
            public static readonly byte Speed = 0;
            public static readonly byte IsDead = 1;
            public static readonly byte AttackTrigger = 2;
        }
    }
}
```

You will use these static IDs in your Burst-compiled jobs to control the animator with zero overhead.

***

#### 🎬 Method 1: Direct Animation Control (Crossfading)

If you want to force a character to play a specific animation immediately (ignoring the Animator Controller's transition arrows), you modify the `AnimatorData` component.

We provide a convenient `.Play()` extension method that automatically handles smooth crossfading between the current animation and the new one.

```csharp
using SnivelerCode.GpuAnimation.Generated;
using SnivelerCode.GpuAnimation.Runtime.Components;
using SnivelerCode.GpuAnimation.Runtime.Utils;
using Unity.Burst;
using Unity.Entities;

[BurstCompile]
public partial struct PlayAnimationJob : IJobEntity
{
    private void Execute(ref AnimatorData animator)
    {
        // Force the character to play the Attack animation
        // The second parameter is the crossfade duration in seconds (default is 0.15f)
        animator.Play(AnimatorGuardCastle.Attack, 0.2f);
    }
}
```

> 💡 **Tip:** Direct control is perfect for combat abilities, hit reactions, or death states where you want immediate responsiveness without relying on complex Animator transition graphs.

***

#### 🎛️ Method 2: Parameter Control (Transitions & Logic)

If you prefer to use the logic you built in Unity's Animator window (e.g., transitioning from Idle to Run when the Speed parameter exceeds `0.1`), you will interact with the `AnimatorParameterData` buffer.

We provide a fluent builder API to make setting parameters clean and readable inside your jobs.

```csharp
using SnivelerCode.GpuAnimation.Generated;
using SnivelerCode.GpuAnimation.Runtime.Components;
using SnivelerCode.GpuAnimation.Runtime.Utils;
using Unity.Burst;
using Unity.Entities;[BurstCompile]
public partial struct UpdateMovementJob : IJobEntity
{
    public float DeltaTime;

    private void Execute(ref DynamicBuffer<AnimatorParameterData> paramBuffer)
    {
        float currentSpeed = 1.5f; // Calculated from your movement logic

        // Set the "Speed" parameter to 1.5f
        AnimatorParams.GuardCastle.Speed.Value(currentSpeed).Apply(paramBuffer);
    }
}
```

The `AnimatorProcessSystem` will read this buffer every frame. If the `Speed` value satisfies a transition condition you set up in the Unity Animator (e.g., `Speed > 0.1`), the system will automatically trigger the transition and handle the crossfade!

***

#### ⚡ Handling Triggers

Triggers in Unity's Animator are special `boolean` parameters that automatically reset to false once they are consumed by a transition.

Our DOTS system perfectly replicates this behavior. If a parameter was defined as a `Trigger` in your original `Animator Controller`, you simply set its value to `1.0f` to fire it.

```csharp
// Fire the Attack Trigger
AnimatorParams.GuardCastle.AttackTrigger.Value(1.0f).Apply(paramBuffer);
```

Once the `AnimatorProcessSystem` detects this and starts the transition to the Attack state, it will **automatically reset the value back to 0.0f** in the buffer, ensuring the animation doesn't loop endlessly.

***

#### ⏱️ Manual Time Control

Sometimes you need absolute control over an animation's playback time (for example, syncing a door opening to a specific puzzle state, or freezing an enemy in ice).

You can take manual control by setting the `ManualControl` flag on the `AnimatorData` component.

```csharp
private void Execute(ref AnimatorData animator)
{
    // 1. Enable manual control (stops automatic time progression)
    animator.ManualControl = true;
    
    // 2. Set the exact time in seconds
    animator.Time = 1.25f; 
}
```

Note: When `ManualControl` is true, automatic transitions and parameter logic are ignored for that specific entity.


---

# 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://sniveler-code.gitbook.io/dots/gpu-animation-entities-pro/7.-runtime-control-c-ecs-api.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.
