Skip to content

The Animation Controller

Ancient edited this page Mar 27, 2026 · 1 revision

The AnimationController is the core class for managing animations in PulseLib animatables.

It provides an entry point to control animations through the AnimationStateHandler

  • Each AnimationController handles ONE animation at a time
  • Animatables can have multiple controllers, allowing multiple animations to run simultaneously

How it works

When creating an animatable, you’ll implement the registerControllers method. This is where you add as many controllers as you need:

    public void registerAnimationControllers(PAnimationManager.PAnimationRegistrar<?> registrar)
    {
    }

Note

If your animatable does not have any animations, you do not need to register any controllers.

Controllers are added to the registrar and configured as needed.

Example: Basic conditional controller
   @Override
   public void registerAnimationControllers(PAnimationManager.PAnimationRegistrar<TestBlockEntity> registrar)
   {
      registrar.add(new PAnimationController<>(animatableState ->
      {
         TestBlockEntity blockEntity = animatableState.animatable();
         PAnimationController<TestBlockEntity> controller = animatableState.controller();
         if (blockEntity.isPlayAnimation())
         {
            controller.play(ANIMATION);
            return ControllerState.PLAY;
         }
         else
         {
            controller.stop();
            return ControllerState.STOP;
         }
      }));
   }

Multiple Controllers

  • The order of registration matters.
  • Controllers are executed in registration order; later controllers can override earlier ones.

Recommendation:

Register broad animations first (e.g., walking, idling), then more specific animations (e.g., attack, interact) afterwards. Example: A walk/idle controller first, followed by an attack controller, allows the entity to swing its arm while walking — blending animations naturally.

Controller Settings

When creating an PAnimationController, you can pass several parameters:

  • name – A unique name for the controller, typically related to its purpose (e.g., "Walking").
  • animationHandler – A predicate (StateHandler) that decides which animation(s) should play and when. See the StateHandler for details.

The StateHandler

The AnimationStateHandler determines what animation a controller plays and when.

Note

StateHandler is called every render frame, allowing real-time animation updates. Treat it as the controller’s current “state,” not as a start/stop trigger.

Examples

Example 1 - Basic idling
public void registerAnimationControllers(PAnimationManager.PAnimationRegistrar<?> registrar) 
{
   registrar.add(new PAnimationController<>("idling", animatableState ->
            {
               if (animatableState.animatable().isIdling())
               {
                  controller.play(IDLE);
                  return ControllerState.PLAY;
               }
               else
               {
                  controller.stop();
                  return ControllerState.STOP;
               }
            }));
}

This controller plays an idling animation when the animatable is idle, or stops the animation otherwise.

Example 2 - Walking + Running + Idling
public void registerAnimationControllers(PAnimationManager.PAnimationRegistrar<TestEntity> registrar)
{
   registrar.add(new PAnimationController<>("walk/idle/run", state ->
   {
      if (state.animatable().isMoving())
      {
         state.controller().play(TestEntity.this.isSprinting() ? RUN : WALK);
         return ControllerState.PLAY;               
      }
      else
      {
        state.controller().play(IDLE);
        return ControllerState.PLAY;
      }
   }));
}

This example chooses between walking, running, or idling depending on movement and sprinting status.

Notice we never return STOP; the controller is always playing an animation.

Example 3 - Spawning
   public void registerAnimationControllers(PAnimationManager.PAnimationRegistrar<TestEntity> registrar)
   {
      registrar.add(new PAnimationController<>("spawn", state -> 
      {
         if (MyEntity.this.tickCount < 100)
         {
            state.controller().play(SPAWN_ANIMATION);
            return ControllerState.PLAY;
         }
         return ControllerState.STOP;
      }));
   }

Plays a spawn animation for the first 100 ticks (5 seconds) after the entity enters the world. After 100 ticks, the controller stops.

Example 4 - Attack animation
   public void registerAnimationControllers(PAnimationManager.PAnimationRegistrar<TestEntity> registrar)
   {
      registrar.add(new PAnimationController<>("attack", state -> 
      {
         if (state.animatable().swinging)
         {
            state.controller().play(ATTACK);
            return ControllerState.PLAY;
         }
         return ControllerState.STOP;
      }));
   }

Plays an attack animation when the entity is swinging its arm. If the entity stops swinging, the controller resets and stops the animation.

Clone this wiki locally