How to improve performance with a lot of meshes

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Kallistotele

I’m making a Tron clone, the trail of the cycles generates a lot of vertexes every second and they never disappear.
The render is a Mesh.Primitive_triangles type, I thought it would have been easy to render but after a while the game starts to go very slow.
What are the settings of the material (spatial) that I should use? Are there other ways to improve performance?

Idk if the image is visible

the picture is not visible, but whty do you need some many vertexes? I mean, the trail from trone is basically a long rectangle surface, you need like 4 vertexes per each motorcycle turn

Andrea | 2021-03-15 11:58

The trail has to be rendered to create the collision even if you don’t turn, so I need to create 4 vertexes every frame and update the collisions.

Kallistotele | 2021-03-15 12:40

do you mean 4 vertexes or 4 additional vertexes?

if you mean 4 vertexes, and updating the position/collission on every frame is still too much for the engine, than maybe think about skipping some frames (it’s not like anybody will notice if the collision trail is a few pixel shorter than what is supposed to be), and maybe find a way of placing the geometry update on a secondary thread.

if you mean 4 additional vertexes each frame, than go back to 4 vertexes only

Andrea | 2021-03-15 12:49

I mean additional vertexes. Do you mean to change the vertex position of the same 4 vertexes and create new ones only when you turn?
I thought you couldn’t change vertex position, also I don’t know how to slow down the process method, i tried to use a timer but it doesn’t seem to work

Kallistotele | 2021-03-15 13:02

yes i mean that: i suppose you are using a Immediate geometry to create the trail, and i suppose you create a new array of point every frame, and pass this array of points into the immediate geometry using something similar to:

for p in array:
   $immediate_geometry.add_vertex(p)

if this is what you do, you can keep doing that but limit the number of points to 4 for each turn. Eg:

var arr=PoolVector2Array()
func _ready();
arr.append(Vector2(0,0))

func _process():
 if turning:
    arr.append(Vector2(motorcycle.translation.x, motorcycle.translation.z))
 $immediate_geometry.clear()
 $immediate_geometry.begin()
 for p in arr:
    $immediate_geometry.add_vertex(Vector3(p.x, 0, p.y))
    $immediate_geometry.add_vertex(Vector3(p.x, trail_height, p.y))
 $immediate_geometry.add_vertex(Vector3(motorcycle.x, 0, motorcycle.z))
 $immediate_geometry.add_vertex(Vector3(motorcycle.translation.x, trail_height, motorcycle.translation.z))
 $immediate_geometry.end

Andrea | 2021-03-15 13:10

ImmediateGeometry is very slow (even for a few dozen vertices), I wouldn’t recommend ever using it in Godot 3.x. Even with only 4 vertices, its use had to be replaced with a mesh in Sprite3D: Use mesh instead of immediate for drawing Sprite3D by clayjohn · Pull Request #39867 · godotengine/godot · GitHub

Calinou | 2021-03-15 13:20

Actually I’m using a SurfaceTool inside a MeshInstance Node.
Immediate Geometry doesn’t let you create collisions from meshes, that said I’ going to try reducing the amount of vertexes as you said

Kallistotele | 2021-03-15 13:24

Ok I’m noob and I can’t fix the code myself. I created a timer for the generation of the vertexes, it has to be 0.017 seconds or less, or the trail is not rendered precisely.
A second timer creates the collision box every 0.07 seconds, it does improve performance if i increase the time, but i need the collisions to exist as soon as possible.
This is the code:

func _on_Timer_timeout():
if is_target and wr.get_ref():
	surfTool.begin(Mesh.PRIMITIVE_TRIANGLES)
	surfTool.add_vertex(prev_point1)
	surfTool.add_vertex(prev_point2)
	
	surfTool.add_vertex(Vector3(p.x,p.y+l,p.z))
	prev_point1 = Vector3(p.x,p.y+l,p.z)
	
	surfTool.add_vertex(Vector3(p.x,p.y-l,p.z))
	prev_point2 = Vector3(p.x,p.y-l,p.z)

	surfTool.add_index(0)
	surfTool.add_index(1)
	surfTool.add_index(2)
		
	surfTool.add_index(1)
	surfTool.add_index(2)
	surfTool.add_index(3)
	
	surfTool.index()

	surfTool.commit(m)
	set_mesh(m)
else:
	get_parent().queue_free()

func _on_Refresh_timeout():
get_parent().get_child(1).shape = mesh.create_trimesh_shape()

Kallistotele | 2021-03-17 19:23

it’s not clear what you have done since we are missing what prev_point and p are, but does this work or not?
if it works, do you notice any stuttering?

ps: i dont know if that’s faster, and sometimes it brokes the collision shape, but have you thought about using scale?

pps: for the timer, i would have used a simple counter, like (but i dont know which method is the most efficient tbh)

var t=0
func _process(_delta):
  t+=1
  if t>refresh_time:
     t=0
     do_stuff()

Andrea | 2021-03-18 15:35

It works, but after a while the game gets slower. I thought about resizing the mesh, but it would scale it on both directions
prev points are the previous point that I used a vertexes, and p is the position of the player

Kallistotele | 2021-03-18 16:25

yeah you have to scale it and move it at the same time.
strange though, if vertex count stays the same it shouldnt get worst over time

Andrea | 2021-03-18 22:42