-
-
Notifications
You must be signed in to change notification settings - Fork 128
Defining Animations in Code (Geckolib4)
While the basic concept of animating models is fairly straightforward in GeckoLib, the nuances can build up or provide edge cases that may catch you off-guard. This page is written to help cover the extra details and information that might be helpful in determining the correct or best way to implement your controllers and animations in the context of GeckoLib.
All animatable objects in GeckoLib3 must implement the GeoAnimatable
interface in one way or another. This is the base interface that represents all animatables.
It is extremely highly recommended however that you implement the interface closest resembling the one for your animatable object.
For example if you are making an Item, you would implement GeoItem
, or GeoBlockEntity
for a BlockEntity, etc.
This interface then requires that you override two methods:
getAnimatableInstanceCache
registerControllers
AnimatableInstanceCaches are collection objects that hold and provide the animatable instances of the animatable object you're creating. This is done to differentiate instances so that they don't all animate the same as the same time. The way it does so varies between animatable types - for example an animatable item's cache will contain an instance for every unique ItemStack, whereas an entity's cache will only contain the single instance of the entity itself.
Because of this, is is IMPORTANT that you instantiate your factories with GeckolibUtil.createInstanceCache
, and not by using the cache constructors. This allows Geckolib to choose the right cache type for your object
AnimationControllers are a multi-faceted object that is designed for a singular purpose: to handle a single concurrent animation. Because of this, it is important to note that a controller can only handle one animation at a time. Attempting to have it run another animation will cause it to drop the previous one.
In order to run multiple animations on an animatable, you need to register multiple controllers - one for each concurrent animation. Note that animations operate on the same model, so you cannot have two animations operating on the same bone, otherwise they may conflict and cause unexpected visual errors. Controllers are run in order of registration however, so if you need to handle collisions gracefully, the lower in the registration order the controller is, the higher its priority when it comes to determining the final position of a bone for that render frame.
An animation controller has three possible states. You can find out what state a controller is in by calling AnimationController.getAnimationState
State | Explanation |
---|---|
Running | Indicates that the controller is actively playing an animation |
Transitioning | Controller is transitioning from stopped to running or from one animation to another |
Stopped | Controller is not actively running an animation. Either completely still or lerping back to the model's original state. |
To tell a controller to start/run a new animation, you call AnimationController.setAnimation
. This call caches the last provided builder, so you can safely call this method every time even if the animation is already playing without a performance penalty or conflict.
Because of this caching, animations that do not loop will only be playable once, even if calling setAnimation
again. If you want to play a non-looped animation again, you'll need to call AnimationController.forceAnimationReset
. This forces the controller to load the next call as a new animation, even if it matches the one that's already cached.
You do not need to do this if you had already run another animation since the last time you played the non-looping animation.
When instantiating your controller, you will need to implement a function that handles an AnimationState
. This function is called every render pass, and is where you set your controller's animations.
This state instance is created anew every render frame, and is directly connected to the controller.
The PlayState
value you return from this function determines the animation state for the controller for the current render frame.
Returning PlayState.CONTINUE
will tell the controller to start or continue the set animation, whereas returning PlayState.STOP
will tell it to stop immediately
By default, GeckoLib attempts to transition linearly between one bone position and another, either when moving from one animation frame to the next, or one animation to the next.
This transition is determined by the transitionLength
value in AnimationController
, and is the int value you set when you instantiate the controller. The field is accessible, so if you want to change the transition length dynamically you can do so via that field.
Setting the value to 0 disables the transition, and instead snaps to the next position as soon as possible.
When the controller attempts to transition between one bone position and another, the default transition is linear. This transition can be configured however to be other types of transitions, such as stepped
or elastic
to give it a more interesting aesthetic.
By default this is handled in the animation json itself, but you can force the controller to use an easing of your choice via calling AnimationController.setOverrideEasingType
field to and instance of EasingType
.
Setting the value to null
will revert back to using the animation json easing definitions.
GeckoLib allows you to provide your own easing type.
This is done by passing a new instance of EasingType
to GeckoLibUtil#addCustomEasingType
at mod startup.
Your function take in a double, and return another double, where the input is a number between 0 to 1, indicating how far in a keyframe you are, and the output is the "eased" number. To read more about how this works and for a better explanation, look at easings.net.
Then
Geckolib 3
Geckolib 4
- Installation
- Getting Started
- Upgrading from GeckoLib 3.1.x to 4.0
- Updating to GeckoLib 4.5
- Basic
- Advanced
- Miscellaneous
Package repository hosting is graciously provided by Cloudsmith.
Cloudsmith is the only fully hosted, cloud-native, universal package management solution that enables your organization to create, store and share packages in any format, to any place, with total confidence.