The bug
Certain entities render weirdly in when inside spawners, stuttering backwards. This happens both while the spawner is active and while the spawner is not active, but is generally much easier to see when it's not active (since the stutter happens quite quickly).
Affected entities
Here's a table of the various situations where this can be found.
The WF column indicates whether or not my suggested fix would solve the issue for this entity. If ✔ , then it's solved completely; in most cases when it's ❌ it's solved for when the spawner is not spinning and partialTicks
is unused but not solved when partialTicks
is used.
The L column refers to the location where the offending code is. R
means the renderer: a direct reference to partialTicks
. M
means the model: A reference to ageInTicks
, which is generated via RenderLivingBase.handleRotationFloat
.
Entity | WF | L | Depends on | Spawner NBT | Notes |
---|---|---|---|---|---|
Charged creeper | ✔ | R |
|
| Charge "armor" translates sideways as a function of time |
jeb_ sheep | ✔ | R |
|
| jeb_ sheep easter egg: wool cycles through all colors. Almost impossible to notice due to the partialTicks portion being very small, but detectable by comparing RGB values between screenshots. |
Wither aura | ✔ | R |
|
| Low health "armor" translates sideways as a function of time |
Arrow shaking | ❌ | R |
|
| While it does normally shake, the shake is supposed to be sinusoidal, not rapidly alternating like that. |
Dying entities | ❌ | R |
|
| Logic present both for regular entities and dragons specifically |
Shulker bullet | ✔ | R |
|
| Spins around |
Lit TNT Minecart | ❌ | R |
|
| Most notable with fuse of 1, but present for all values under 10. Fuse must be specified, though, or else it defaults to -1. |
Primed TNT | ❌ | R |
|
| TNT expands |
Ender crystal | ❌ | R |
|
| Crystal rotation; stutter isn't significant |
Bat | ✔ | M |
|
| Bat flapping wings |
Blaze | ✔ | M |
|
| Blaze rods |
Ender crystal (2) | ✔ | M |
|
| Crystal height; stutter is significant |
Endermite | ✔ | M |
|
| Model swaggering |
Ghast tentacles | ✔ | M |
|
| Ghast tentacles |
Guardian spikes | ✔ | M |
|
| Only noticeable if inside the guardian model itself (spectator mode), though slightly visible from outside |
Silverfish | ✔ | M |
|
| Model swaggering |
Vex wings | ✔ | M |
|
| |
Phantom wings/tail | ✔ | M |
|
|
To reproduce
You need to have over 20 frames per second to see this effect in-game. If your FPS is locked at or below 20 it will be more or less impossible to notice.
The non-spinning-spawner variant of this issue is much easier to reproduce.
Switch to spectator mode (
/gamemode 3
), so that the spawner doesn't spin even if you're closeUse
/setblock ~ ~ ~ minecraft:mob_spawner replace
with the given data to create the appropriate spawner.Observe the spawner. In some cases, you'll need to fly really close (or even inside) the spawner to see the effect
To reproduce with a spinning version, add Delay:10000
to the spawner NBT such that the spawner spins extremely slowly. (Previously, I recommended using cheat engine to slow the game, but @unknown suggested this better way).
Switch to creative mode (
/gamemode 1
).Use
/setblock ~ ~ ~ minecraft:mob_spawner replace
with the given data to create the appropriate spawner.Watch the spawner, trying to see the stutter while it's spinning.
Cause
These entities all have an animation that occurs as a function of both a variable on the entity (usually the time it has existed for) and the distance into the current tick (partialTicks
). The reliance on partialTicks
is what causes it to stutter, while the reliance on the time it has existed for is what causes it to not advance to the next part of the animation.
Suggested fix
There is no real good fix for this, but the best fix I can come up with is tweaking the way spawners render so that when the spawner is spinning, ticksExisted
is updated, and when it is not spinning, partialTicks
is always set to 0. That way, the animations play normally when the spawner is spinning, and when it isn't spinning, it doesn't attempt to animate a nonexistent animation.
This could be done by adding this code into MobSpawnerBaseLogic.updateSpawner
(ajg.c
, line 62):
if (cachedEntity != null) {
// This null check may be unneeded.
// Update the entity's existence ticks, for rendering purposes
cachedEntity.ticksExisted++;
}
And then also adding this code into TileEntityMobSpawnerRenderer.renderMob
(bsn.a
, line 17):
if (!mobSpawnerLogic.isActivated()) {
// Don't interpolate the position if the spawner isn't rotating
partialTicks = 0;
}
This doesn't help with all entities, but it does solve it for the common of them.
An alternative fix would be to always use partialTicks
set to 0, even if the spawner is spinning. This will prevent any kind of issue, but in my opinion is a slightly less interesting graphical effect.
Comments


the suggested fix works for most things. The other things could be fixed by simply changing the animation to based on ticks rather then changing it on entity.update() would be my guess.
you ignored the fact that entities in spawners can and will have passengers aka jockey spawners. You need to get and cache the recursive passengers and the entity into a list. from there then you can do entity.ticksExisted++;
Also affected the bees.
Can confirm in 21w03a.
Can confirm in 21w05b.
Can confirm in 21w06a.
Relates to:
MC-87183
MC-3867