Triggerable Animations
GeckoLib supports 'one-shot' animations that can be triggered at any time.
Overview
Normally when animating, you would test for conditions in your AnimationController's StateHandler, and tell the controller
to animate or not depending on those conditions.
This can get cumbersome when you just want to play an animation now and don't really care about any other conditions.
GeckoLib provides a way to trigger animations directly from either the server or client side to resolve this.
Usage
To use triggered animations, you first need to register the triggerable animation on the AnimationController.
This is done when constructing your controller, by appending .triggerableAnim.
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
controllers.add(new AnimationController<>(this, "shoot_controller", animTest -> PlayState.STOP)
.triggerableAnim("shoot", DefaultAnimations.ATTACK_SHOOT));
}
This example registers a controller called shoot_controller, with a triggerable animation identified by shoot.
To trigger the animation, you then call triggerAnim on your animatable instance.
@Override
public InteractionResult mobInteract(Player player, InteractionHand hand) {
if (!level.clientSide())
triggerAnim("shoot_controller", "shoot");
return InteractionResult.sidedSuccess(level().isClientSide());
}
In the above example, we trigger the shoot animation we registered earlier whenever the entity is interacted with.
Items
Because items are singleton objects (only one is registered in the game at a time), triggerable animations for items need slightly more work.
Firstly, you have to tell GeckoLib that your Item is network-synced so that GeckoLib knows how to find it.
This is done by adding the below code to your item's constructor:
public ExampleItem(Properties properties) {
super(properties);
GeoItem.registerSyncedAnimatable(this);
}
Then, when triggering the animation, you must provide the entity the item belongs to, as well as the ItemStack's sync id.
public InteractionResult use(Level level, Player player, InteractionHand hand) {
if (level instanceof ServerLevel serverLevel)
triggerAnim(player, GeoItem.getOrAssignId(player.getItemInHand(hand), serverLevel), "shoot_controller", "shoot");
return InteractionResult.sidedSuccess(level.isClientSide());
}
Armor
Armor has similar setup and usage requirements to items, but because armor is technically two possible animatables (the ItemStack,
and the worn armor model), there are two options for triggering the animation.
If you want to trigger an animation on the worn armor model, you can use the triggerArmorAnim method.
Stopping Triggered Animations
When using triggered animations, you may find you need/want to stop an animation before it finishes naturally.
This is possible in much the same way that triggered animations work, but instead of calling triggerAnim, you call
stopTriggeredAnim, using the same arguments you did to start it.
Trigger-Only AnimationController
If you are using triggered animations and find yourself only needing a controller to trigger animations, GeckoLib provides the
DefaultAnimations#triggerOnlyController factory, which will create a controller that doesn't have any native animations,
with the name Actions.
Example Implementation
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
controllers.add(DefaultAnimations.triggerOnlyController()
.triggerableAnim("Bite", DefaultAnimations.ATTACK_BITE));
}
Use Cases
There are a few common use-cases for triggered animations, in case you're having trouble figuring out how to best use them.
One-off Animations
You might use triggered animations for an animation that you just want to play once, now. For example, a gun's firing animation, or a monster roaring. Using triggered animations for this means you don't have to keep track of the animatable's state, you can just tell it to play the animation and be done.
Animation Transitions
This is a common use-case that people forget about.
When you are transitioning from one animation state to another (E.G., walking to sitting down), you might want an animation that does the 'sitting down' and 'standing up' transition.
This can get very complicated when trying to keep track of the various transition states in variables.
Instead, we can have the controller just handle the walking and sitting, depending on which the animatable should be doing.
Then, when we want to switch between the two, we can use a triggered animation for 'standing up' or 'sitting down'
which will automatically disguise the swap.
Example Implementation
Below we have an example of an animation transition controller, disguising a transition between walking and sitting.
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
controllers.add(new AnimationController(animTest -> {
// This check is made up for this example, to simplify it
// Be in sitting pose if sitting
if (checkIsSitting())
return animTest.setAndContinue(MY_SITTING_ANIM);
// Walk or idle if not sitting
return animTest.isMoving() ? animTest.setAndContinue(DefaultAnimations.WALK) : animTest.setAndContinue(DefaultAnimations.IDLE);
}).triggerableAnim("Sit", SIT_DOWN_ANIM) // Triggerable anim to 'stand up'
.triggerableAnim("Stand", STAND_UP_ANIM)) // Triggerable anim to 'sit down'
}