Heads up!
This page assumes you have exported the assets properly as per How to Export Your Project
How to animate Entities
Creating your custom AzEntityAnimator
For this, you will create a class which extends AzEntityAnimator
. This class will handle the registration of animation controllers and providing the animation file's location for the animations.
Example:
public class ExampleEntityAnimator extends AzEntityAnimator<ExampleEntity> {private static final ResourceLocation ANIMATIONS = ResourceLocation.fromNamespaceAndPath(YOUR_MOD_ID,"animations/entity/example_entity.animation.json");@Overridepublic void registerControllers(AzAnimationControllerContainer<ExampleEntity> animationControllerContainer) {animationControllerContainer.add(AzAnimationController.builder(this, "base_controller").build());}@Overridepublic @NotNull ResourceLocation getAnimationLocation(ExampleEntity animatable) {return ANIMATIONS;}}
Some highlights of the above example.
-
ANIMATIONS
: This stores theResourceLocation
reference to the animation JSON file. You need to replaceYOUR_MOD_ID
with your mod's ID and ensure the file path matches your JSON animation file. -
registerControllers()
Registers the animation controllers that will define the animation behavior and states for the item. You can multiple if needed.
Creating an Animation Dispatcher
This class isn't required but is highly suggested to help store your animation commands to call in other classes.
Example:
public class ExampleEntityDispatcher {private static final AzCommand IDLE_COMMAND = AzCommand.create("base_controller","idle",AzPlayBehaviors.LOOP);private static final AzCommand WALK_COMMAND = AzCommand.create("base_controller","walking",AzPlayBehaviors.LOOP);private static final AzCommand RUN_COMMAND = AzCommand.create("base_controller","running",AzPlayBehaviors.LOOP);private static final AzCommand DEATH_COMMAND = AzCommand.create("base_controller","death",AzPlayBehaviors.HOLD_ON_LAST_FRAME);private final ExampleEntity example_entity;public DoomHunterAnimationDispatcher(ExampleEntity animatable) {this.example_entity = animatable;}public void idle() {IDLE_COMMAND.sendForEntity(example_entity);}public void walk() {WALK_COMMAND.sendForEntity(example_entity);}public void run() {RUN_COMMAND.sendForEntity(example_entity);}public void death() {DEATH_COMMAND.sendForEntity(example_entity);}}
Accessing your Dispatcher to trigger animations
You will now define your ExampleEntityDispatcher from above in your Entities class. It is also recommand to register the MoveAnalysis utility class if you'd like to do movement based animations.
public class ExampleEntity extends Entity {// This is your class where you will setup the AzCommands/Animations you wish to playpublic final ExampleEntityDispatcher dispatcher;public final MoveAnalysis moveAnalysis;public ExampleEntity(EntityType<? extends Entity> entityType, Level level) {super(entityType, level);// Create the instance of the class here to use later.this.dispatcher = new ExampleEntityDispatcher(this);this.moveAnalysis = new MoveAnalysis(this);}}
Now you simply call the dispatcher wherever you want to play the animations.
Example of playing a death animation, movement animations and an idle animation.
@Overridepublic void tick() {super.tick();moveAnalysis.update();if (this.level().isClientSide) {var isMovingOnGround = moveAnalysis.isMovingHorizontally() && onGround();Runnable animationRunner;if (!this.isAlive()) { // if dead, play death animationanimationRunner = animationDispatcher::death;} else if (isMovingOnGround) {if (this.isAggressive()) { // if moving and aggressive, play runninganimationRunner = animationDispatcher::run;} else { // if moving but not aggressive play walkanimationRunner = animationDispatcher::walk;}} else { // Play the default idle animationanimationRunner = animationDispatcher::idle;}animationRunner.run();}}
Creating your Renderer
This renderer is responsible for how your custom entity is displayed in the game.
It connects the entity with the following:
- Geometry file (
geo.json
): Defines the 3D model of the entity. - Texture file (
.png
): The visual appearance of the entity (applies over the geometry). - Animator: Animations for the entity, provided by
ExampleEntityAnimator
.
The renderer class must extend AzEntityRenderer<ExampleEntity>
and provide the required configuration.
Heads up!
See AzRendererConfigs 101 for all AzBlockEntityRendererConfig#builder options.
Example Renderer
public class ExampleEntityRenderer extends AzEntityRenderer<ExampleEntity> {private static final ResourceLocation GEO = ResourceLocation.fromNamespaceAndPath(YOUR_MOD_ID,"geo/entity/example_entity.geo.json");private static final ResourceLocation TEX = ResourceLocation.fromNamespaceAndPath(YOUR_MOD_ID,"textures/entity/example_entity.png");public ExampleEntityRenderer() {super(AzBlockEntityRendererConfig.<ExampleEntity>builder(GEO, TEX).setAnimatorProvider(ExampleEntityAnimator::new).build());}}
Registering your Renderer
Nothing special is required here! Simply call render your entity render as per the standard use case of your modloader.