[ANDROID] - Optimizing game, and TileMap makes fps drop.

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Wiskam
:warning: Old Version Published before Godot 3 was released.

Hi everyone.
I’m trying some little things on Android, especially terrain generation.

The first step I would like is filling an area with tiles, so I’m using a while loop like this:

func _UpdateGrass():
	startchunk = get_node("TileMapFloor").world_to_map(Vector2(campos.x-1080, campos.y-1080))
	actualchunk = startchunk
	endchunk = get_node("TileMapFloor").world_to_map(Vector2(campos.x+2160, campos.y+3000))
	while(actualchunk != endchunk):
		if (actualchunk.x < endchunk.x):
			get_node("TileMapFloor").set_cell(actualchunk.x, actualchunk.y, 0)
			actualchunk = Vector2(actualchunk.x+1, actualchunk.y)
		elif (actualchunk.x == endchunk.x):
			get_node("TileMapFloor").set_cell(actualchunk.x, actualchunk.y, 0)
			actualchunk = Vector2(startchunk.x, actualchunk.y+1)
	if actualchunk == endchunk:
		get_node("TileMapFloor").set_cell(actualchunk.x, actualchunk.y, 0)
	pass

For the moment, it’s only one tile, I know, but I will make it more complicated once I will manage to fix a major issue.


This major issue is about the TileMap on Android, once the function _UpdateGrass() has been executed, the game is lagging and FPS drop from 50(without the TileMap) to 07, which is obviously bad. (50 isn’t really good either but well…)

I would like to find a way to optimize the game, maybe with a chunk system which is really common on randomly-generated-terrain games, but I don’t know how to proceed.

Right now, this is the area covered by this function according to a 1080*1920 resolution (everything in dark grey and light grey are covered by the area):

So that’s an area of 6 screens.
I tried to compress my tileset.tex (which is used to build the Tileset scene) using the “Compress WebP : 0.2”, the “Compress PNG” and “Compress VRAM”, but any of them make the fps higher.

Each tile of my tileset are 64x64 images like this one:


Every tips are welcome, I can give more information if needed but the main fps drop issue is due to my TileMap.

for one tip, save the reference of node and use it.

func _UpdateGrass():
    var tilemap = get_node("TileMapFloor")
    startchunk = tilemap.world_to_map(Vector2(campos.x-1080, campos.y-1080))
    ....

volzhs | 2016-05-26 12:55

Well thanks that was on my optimization list but that doesn’t affect the fps, always 07.

Wiskam | 2016-05-26 13:29

Can you post a sample project for it?
And you can use Profiler on debugger if you compile godot tool with github head, like this.

volzhs | 2016-05-26 13:48

as short, you filled 3240 x 4080 area with 64x64 tile, and it’s slow right?

volzhs | 2016-05-26 14:01

I don’t really know how to use Profiler, I guess it’s a fps graph but well, fps are staying between 05 and 08 during the test on Android with OS.get_frames_per_second().

That’s exactly this, it gets really slow when I fill this area. Smaller area (like 1080*1920) makes the fps higher, like 25 fps, which isn’t really good but this is a too small area for my project.

Unfortunately I would like to avoid sending a public sample of my project, but I think it can be reproduced easily with a 1080*1920 scene, a TileMap filled with GdScript and a FPS counter.

This is my scene tree:

And here is my GAME script, where the TileMapFloor is generated and other things.
http://pastebin.com/tXhVHTuu

Wiskam | 2016-05-26 19:21

On mobile devices, fill rate can be limited (slower to draw pixels). So the less pixels you draw, the better (yes, even transparent ones!).
Are all 4 tilemaps filled with tiles? Is your Android screen really having a 1080x1920 resolution? Does your device usually runs games smoothly?

Another thing to keep in mind, how many textures are there in your tiles?
The more different textures, the slower it will be, because the graphic card has to change states for every tile. For this, it is recommended to use atlases (one big texture with all tiles in it), so the graphic card can reuse the same texture to draw all tiles.
You can make your atlas and define sub-rects, or use image groups.

Godot Tilemaps are somehow infinite, they already have a chunk-based layout internally, so only visible chunks are drawn. You can customize the size of the chunks with the quadrant size parameter.

If you cannot provide your project, can you at least reproduce your case with a minimal project and placeholder tiles?

Note: writing pass at the end of every function is not required, unless it is empty :slight_smile:
Note 2: you can use tilemap.set_cellv(position, cell) to set cells, it’s faster than tilemap.set_cell(position.x, position.y, cell

Zylann | 2016-05-26 22:32

Hi Zylann, wow so many info that’s great thank you :slight_smile:

" Note: writing pass at the end of every function is not required, unless it is empty :) "
" Note 2: you can use tilemap.set_cellv(position, cell) to set cells, it's faster than tilemap.set_cell(position.x, position.y, cell "

I deleted pass where it needs to be deleted, and replace the set_cell by set_cellv, and the game is now between 19 and 22 fps, that’s much smoother and somewhat acceptable for a minimalist game !


" Are all 4 tilemaps filled with tiles? Is your Android screen really having a 1080x1920 resolution? Does your device usually runs games smoothly? "

Only the TilemapFloor is filled by tiles, others aren’t used yet, but I planned to add some trees, rocks, and things like this so TileMapFloor will be the most filled.

My device runs games really smoothly, even 3d games like Real Racing. But I just noticed its screen isn’t 1080*1920 but 720*1280 ! Time to make the script fit to any resolution I think, my bad on this one ^^

Edit: Well I don’t think it’s worth it, I would like every devices to get the same map size so it’s good like this IMO.


" You can customize the size of the chunks with the quadrant size parameter. "

What’s the unity for the quadrant option? According to my research, quadrants are obviously like this if I understand:

But what does the value represent? I tried different value without seeing any visual changes.


" Another thing to keep in mind, how many textures are there in your tiles? "

I cleaned my tileset image, now there is only 5 textures in my tileset.tex and only 3 added to my tileset.res for the moment. But unfortunately it doesn’t save any fps.

Wiskam | 2016-05-27 10:12

:bust_in_silhouette: Reply From: Zylann

I deleted pass where it needs to be deleted, and replace the set_cell by set_cellv, and the game is now between 19 and 22 fps, that’s much smoother and somewhat acceptable for a minimalist game !

Wait… are you calling _UpdateGrass() on every frame? I think the slowdown comes from your script then, not the tilemap :stuck_out_tongue: (I make this assumption because my last two suggestions have almost nothing to do with fps :p)
You should make sure the map is modified only when it needs to, I don’t think grass needs to be updated everytime.

Quadrants: their size is in tiles, by default they are 16x16 tiles. But that’s mostly important for rendering, 16 is usually a good balance.

Hi
Oh OK it took me quite a time to understand why your were thinking _Update Grass() was called every frame, and it’s surely because of the Update word . Well I totally used the wrong word in my function and I have already changed the name function to _CreateGrass(), I don’t know what I had in mind when I named it Update lol.

But no this function is called only one time don’t worry ^^
I also posted the script about this in a comment above, you were able to check that but well it’s OK time is important and you already gave me much with you answers. ^^

That’s strange because set_cellv have considerably increased fps on Android, I made the changes step by step and it’s at this one the fps had increased , like +12 fps.

For the quadrants, I will leave it to 16 since I don’t really master the meaning of that and there is apparently no fps change with different numbers.

I would like to see if anybody else have an idea to save some more fps, I’m currently at 21 fps on my HTC Desire 626. If you would like to post your previous comment about set_cellv and your other tips as an answer, I may select it to be the best answer if anybody find another huge thing, which I doubt.
21 fps is currently quite good but my device is new, so I think older devices will loose some fps right? Below 20 it becomes quite laggy.

Wiskam | 2016-05-27 21:46

This is very strange that set_cellv increased the FPS because it does the exact same thing as set_cell, hence my question. I’m puzzled as to why you get so few fps, and why you got more by changing code that is executed ONCE to do the SAME thing :smiley:

Quadrants: think about them as chunks. In Minecraft, chunks are 16-blocks wide. It goes the same for TileMap, and is also the reason why it can be infinite by design :slight_smile:

Zylann | 2016-05-27 23:03

Oh yeah I see, it can display more than one chunk at a time.
Yeah I can’t understand why fps have increased like this, because the function is called only in func _ready() so once _Create grass() is finished it has nothing to do with fps :confused:

Well now I’m generating water lakes, rocks, trees, and everything is good, fps average still 21. That’s enough for this type of game, it a Dwarf Fortress clone so yeah.

Thanks a lot Zylann, for an unknown reason your tips has been really useful :o
(Post your answer if you want, I will select it )

Wiskam | 2016-05-28 08:41