![]() |
Attention | Topic was automatically imported from the old Question2Answer platform. |
![]() |
Asked By | russiniet |
First of all, simple question. Would grouping nodes and changing the visibility of the group be more optimized in any way than changing visibility of each node individually?
Now, if you have enough dedication and nerves to look through my terrible code, then it would be greatly appreciated if you gave me some tips. So, I am making a 3d project, where you need to build on a 2d grid. First the map is generated. It’s just a two-dimensional array, no optimization needed, but the problem comes later on when I actually need to render the tiles. The map itself is 128x128, so there are 16384 nodes that I need to render, which is obviously a lot. So, first I instantiate the tiles in _ready() function, which adds all the tiles under a Tile Manager node. Tiles are nothing more than cubes with material on them. Then every frame I pick a part of the whole map (I can’t update the whole map in one frame, as it created lag spikes) and either hide or show the tiles that i selected, based on the distance to the camera in order to take weight off the GPU. It works, I get around 90 - 120 FPS, but it’s not so good, considering that it’s only several polygons (I have RX 580). So, is there a way to optimize it somehow? This is how the first question relates to my project - I can split the terrain into chunks and hide the whole chunk instead of looping through each node individually. Would that help?
If you need additional context, here are the scripts.
Generation script:
func generate_map(size_x, size_y):
for x in range(size_x):
map.append([])
map[x] = []
map[x].resize(size_y)
for y in range(size_y):
map[x][y] = {
"elevation": [UNIMPORTANT STUFF],
"reference": null,
"tree": [UNIMPORTANT STUFF]
}
Initial tile instantiation script:
func generate_tiles():
for x in range(global.map.size()):
for y in range(global.map[x].size()):
var new_tile = tile.instance()
new_tile.translate(Vector3(x*2, global.map[x][y].elevation, y*2))
new_tile.visible = false
if global.map[x][y].tree && global.map[x][y].elevation > 0:
new_tile.get_child(2).visible = true
if global.map[x][y].elevation < 1:
new_tile.get_child(0).set_surface_material(0, sand_mat)
add_child(new_tile)
global.map[x][y].reference = get_child(get_child_count()-1)
Tile render function:
func render_tiles(camera_pos, dist, rsx, rsy):
var rex = rsx+16
var rey = rsy+16
if rsx == global.map_size-16: rex = 63
if rsy == global.map_size-16: rsy = 63
for x in range(rsx, rex):
for y in range(rsy, rey):
if x*2 < camera_pos.x+dist && x*2 > camera_pos.x-dist && y*2 < camera_pos.z+dist && y*2 > camera_pos.z-dist:
if not global.map[x][y].reference.visible:
global.map[x][y].reference.visible = true
elif global.map[x][y].reference.visible:
global.map[x][y].reference.visible = false
_process() loop:
frame += 1
#Update only at certain times
if frame > 3:
frame = 0
#Update different "chunk" every frame to distribute the load
render_start_x += 16
if (render_start_x >= global.map_size-16):
render_start_x = -16
render_start_y += 16
render_tiles(get_node("/root/Spatial/Player").translation, render_range, render_start_x, render_start_y)
if (render_start_y >= global.map_size-16):
render_start_y = -16