Posted January 26, 20232 yr Alright, so I have a Block Entity renderer and I want it to have a smooth animation. My current animations work well, other than having a lower framerate, which is obvious. However, when I try interpolating using Partial Ticks, the results vary greatly. Sometimes the animation is perfectly smooth, other times it stutters a lot. From testing I know the varying results are caused by me pausing the game and coming back. When I pause the game, the rendering does indeed stop, but Partial Ticks still do their thing and when I unpause it, Partial Ticks are ahead/behind where they were, which causes the Block Entity animation to start stuttering. How do I get around this issue? Here's my code: (it's basically raising and then lowering five ring models one by one) public class TransportRingsRenderer implements BlockEntityRenderer<TransportRingsEntity> { private static final ResourceLocation TRANSPORT_RINGS_TEXTURE = new ResourceLocation(StargateJourney.MODID, "textures/block/transport_rings.png"); private final ModelPart first_ring; private final ModelPart second_ring; private final ModelPart third_ring; private final ModelPart fourth_ring; private final ModelPart fifth_ring; public TransportRingsRenderer(BlockEntityRendererProvider.Context p_173554_) { ModelPart modelpart = p_173554_.bakeLayer(LayerInit.TRANSPORT_RING_LAYER); this.first_ring = modelpart.getChild("first_ring"); this.second_ring = modelpart.getChild("second_ring"); this.third_ring = modelpart.getChild("third_ring"); this.fourth_ring = modelpart.getChild("fourth_ring"); this.fifth_ring = modelpart.getChild("fifth_ring"); } private float getHeight(int ringNumber, int emptySpace, int transportHeight, int ticks, int progress, float partialTicks) { float ringHeight = 0; int startTicks = 6 * (ringNumber - 1); int movingHeight = progress - 6 * (ringNumber - 1); int staticHeight = transportHeight - 2 * (ringNumber - 1); int stopHeight = transportHeight + 17 - 4 * (5 - ringNumber); if(ticks == progress && progress > startTicks && progress < stopHeight) ringHeight = (movingHeight + partialTicks) * 4; else if(progress >= stopHeight) ringHeight = staticHeight * 4; else if(ticks != progress && progress > startTicks && progress < stopHeight) ringHeight = (movingHeight - partialTicks) * 4; if(emptySpace > 0) return ringHeight; else if(emptySpace < 0) return -ringHeight; return 0; } @Override public void render(TransportRingsEntity rings, float partialTick, PoseStack stack, MultiBufferSource source, int combinedLight, int combinedOverlay) { VertexConsumer vertexconsumer = source.getBuffer(RenderType.entitySolid(TRANSPORT_RINGS_TEXTURE)); // It takes the rings 29 ticks to get into position if there is empty space right above them if(rings.progress > 0) { this.first_ring.y = getHeight(1, rings.emptySpace, rings.transportHeight, rings.ticks, rings.progress, partialTick); this.first_ring.render(stack, vertexconsumer, rings.transportLight, combinedOverlay); } if(rings.progress > 6) { this.second_ring.y = getHeight(2, rings.emptySpace, rings.transportHeight, rings.ticks, rings.progress, partialTick); this.second_ring.render(stack, vertexconsumer, rings.transportLight, combinedOverlay); } if(rings.progress > 12) { this.third_ring.y = getHeight(3, rings.emptySpace, rings.transportHeight, rings.ticks, rings.progress, partialTick); this.third_ring.render(stack, vertexconsumer, rings.transportLight, combinedOverlay); } if(rings.progress > 18) { this.fourth_ring.y = getHeight(4, rings.emptySpace, rings.transportHeight, rings.ticks, rings.progress, partialTick); this.fourth_ring.render(stack, vertexconsumer, rings.transportLight, combinedOverlay); } this.fifth_ring.y = getHeight(5, rings.emptySpace, rings.transportHeight, rings.ticks, rings.progress, partialTick); if(rings.progress <= 24) this.fifth_ring.render(stack, vertexconsumer, combinedLight, combinedOverlay); else this.fifth_ring.render(stack, vertexconsumer, rings.transportLight, combinedOverlay); } }
January 26, 20232 yr partialTicks is a value between 0 and 1, so I believe you are just using it incorrectly. If you have the current position for this tick and the position of the last tick, you can use Mth#lerp to handle the lerping for you.
January 26, 20232 yr Author I know it's a value between 0 and 1, that's why I'm multiplying it by four after adding the previous position to get my preffered outcome. As for the Mth#lerp I've essentially copied the code from that and changed it to fit me needs Mth#lerp code: public static float lerp(float partialTick, float progressOld, float progress) { return progressOld + partialTick * (progress - progressOld); } my code: ringHeight = (movingHeight + partialTicks) * 4; I just removed the initial multiplication of partialTicks by (progress - progressOld) because it always changes by 1 pixel anyway. The movingHeight corresponds to progressOld. Then I multiplied everything by 4 to make it go higher. Math#lerp has the same effect, I just removed it from my code so that I don't have to call the method every time. No other reason really. If it works sometimes and sometimes doesn't, I can't be using it completely incorrectly, right? Or is there perhaps something more Math#lerp does other than the lerping math? Edited January 26, 20232 yr by Povstalec
January 27, 20232 yr 22 hours ago, Povstalec said: If it works sometimes and sometimes doesn't, I can't be using it completely incorrectly, right? Or is there perhaps something more Math#lerp does other than the lerping math? As long as you are using it to handle the interpolation between ticks such that the value is between the previous movement height and the next one, there should be no issue. I assume you know this, so I'll also assume the math is right. In that case, it may have to do with what data is synced to the client or handled by the client. You could try printing out the parameters of the height method and see if there are any unusual values that appear when you pause and then unpause the game.
January 27, 20232 yr Author Alright, so for the sake of testing, I've made another renderer which adds progress in the render method itself and that animation is perfectly smooth (although the progress obviously doesn't stop when I pause the game). That means the problem really is in syncing. I'll try printing out the height like you suggested, but in the meanwhile, do you know how I could fix this? I'm fairly sure my packets are being sent properly and I can't really think of any other place in the code where desync could happen.
January 27, 20232 yr Author Alright, so using the other renderer for printing out the values, I got this: Rotation: 16 P-Rotation: 17.39999 Tick: 131 P-Tick: 0.6999946 Rotation: 16 P-Rotation: 16.35999 Tick: 131 P-Tick: 0.17999458 Rotation: 18 P-Rotation: 19.319988 Tick: 132 P-Tick: 0.6599946 Rotation: 18 P-Rotation: 18.159988 Tick: 132 P-Tick: 0.07999456 Rotation: 20 P-Rotation: 21.19999 Tick: 133 P-Tick: 0.59999454 Rotation: 20 P-Rotation: 20.079988 Tick: 133 P-Tick: 0.03999448 Rotation is the progress of the block entity. P-Rotation is progress with partial ticks (multiplied by two) added. Tick is tick. P-Tick is partial tick. I can see a pattern of the partial ticks reaching value 1 before the tick ends, which means they go back down to 0 during the same tick and that causes the animation to stutter. EDIT: And this is how it looks after pausing the game a few times to get a smooth animation: Rotation: 182 P-Rotation: 182.12 Tick: 185 P-Tick: 0.060000777 Rotation: 182 P-Rotation: 182.76 Tick: 185 P-Tick: 0.38000077 Rotation: 182 P-Rotation: 183.44 Tick: 185 P-Tick: 0.72000074 Rotation: 184 P-Rotation: 184.12 Tick: 186 P-Tick: 0.060000777 Rotation: 184 P-Rotation: 184.76 Tick: 186 P-Tick: 0.38000077 Rotation: 184 P-Rotation: 185.44 Tick: 186 P-Tick: 0.72000074 Rotation: 186 P-Rotation: 186.12 Tick: 187 P-Tick: 0.060000777 Rotation: 186 P-Rotation: 186.76 Tick: 187 P-Tick: 0.38000077 Rotation: 186 P-Rotation: 187.44 Tick: 187 P-Tick: 0.72000074 I'm not sure why it prints 3 values when it was only able to print 2 values per tick just a few minutes ago. Edited January 27, 20232 yr by Povstalec
January 27, 20232 yr 29 minutes ago, Povstalec said: I can see a pattern of the partial ticks reaching value 1 before the tick ends, which means they go back down to 0 during the same tick and that causes the animation to stutter. So partial tick should only rise from 0 to 1. The fact that the value is decreasing on the same tick should not be possible. The fact that the value is jumping down probably means you are handling the client logic and then syncing the server logic at a later point which still has an old value loaded. In that case, I would suggest just doing the render all client side and not doing any of the rendering logic on the server, just syncing any specific key values that determine the animation state. 32 minutes ago, Povstalec said: I'm not sure why it prints 3 values when it was only able to print 2 values per tick just a few minutes ago. Yeah, this looks more correct. The amount of values per tick is generally in correspondence to your refresh rate. I would assume you have the game running at 60fps so there would be three partial ticks for every tick.
January 27, 20232 yr Author Alright, I see what you mean. But there's a slight problem: I'm not doing any logic with the second renderer. I just made an arbitrary value that is raised by one at the end of each tick and gets sent to the client via a packet, nothing else. Any other ideas? Edited January 27, 20232 yr by Povstalec
January 28, 20232 yr Author So I've come to the conclusion that Packets simply aren't sending the info fast enough and removed the use of packets altogether. Instead I'm just doing the same thing on Client as I am on Server, which does result in a smooth animation, but I can't really control the animation, since most of the stuff the animation depends on is server only. Either way, thanks a lot for your help. Edited January 28, 20232 yr by Povstalec
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.