Jump to content

Recommended Posts

Posted

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);
	}
}

 

Posted (edited)

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 by Povstalec
Posted
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.

Posted

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.

Posted (edited)

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 by Povstalec
Posted
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.

Posted (edited)

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 by Povstalec
Posted (edited)

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 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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Hello everyone, As the title suggests I'm new the the entire modding thing I used to make little game projects here and there and since I've started University I've taking Java and I fell in love with it somehow. So I have a couple of questions: Can I learn Java from modding the game (Yes I have the basics) can it expand my knowledge in this language? Does modding require massive teams (I've seen too many projects on curseforge that have like 3-6 contributors) or can I do it solo? Where to start? I know you might be thinking "Whats wrong with this guy just simply google what to do..." and for that I say "I did" and found too many results not saying its a bad thing just you know we have a common term in development in general and that's "Development hell" you guys are more experienced than I'm what tutorial series do you recommend? Why didn't I use Reddit for this question why the minecraftforge forums where we fix issues to modding not help beginners start?  Because it gave me mental issues not saying this for attention but I really dislike the communities there are helpful somewhat but everything I said there regardless of what it is even a simple question in development will be bombarded with hateful comments cruelty and bullying and even worse grammar police , I truly hope that you guys aren't like this...   Please forgive me for my English as I'm not an English speaker. I'm alright with you people criticizing me for the question or the stuff I said just don't be cruel , thanks in advance! 
    • Hi! As the title suggests, I am encountering an issue with the Prominence II mod pack in which my server keeps crashing at random intervals. I am hosting it through Aternos, and below is a copy of my crash log. I have tried googling solutions and all forums are years old. I am new to hosting a server and don't know my way around files. I have also contacted Aternos support and they said it was a problem with the trinket mod? However I don't know if removing it will solve or corrupt my world. Any help would be greatly appreciated!   https://mclo.gs/RWmkEtK
    • I've been trying to render a line on the screen for a few days now, and everywhere I've looked has outdated answers. They say to use RenderGameOverlayEvent, which has been removed by my understanding. Is there a specific event I should be using or anything else I'm doing wrong? Tesselator tesselator = Tesselator.getInstance(); BufferBuilder renderer = tesselator.getBuilder(); renderer.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR); Color c = new Color(255, 0, 0, 255); renderer.vertex(0, 100, 0).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).endVertex(); renderer.vertex(0, 200, 0).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).endVertex(); tesselator.end(); Based on what I've seen, this is the code that should be working, though I feel that I need to override an event and add it in. What event should I be using for this? Is there another way of doing it that I don't know of?
    • yes i did it, we installed the drivers from nvidia website
    • Wait, how did you fix it?      
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.