When you change the radius of a
SphereMesh (I assume it’s a
SphereMesh, not a
MeshInstance), the engine has to recompute the entire mesh that composes it, which is actually made of TONS of vertices. If you do this every frame with a hundred of cells, that’s going to put pressure on the CPU and hammer the graphics card with hundreds of new meshes to upload every frame.
Worse, I guess you made that mesh unique so that each cell can grow independently. This is very bad, because it’s copying the mesh for every cell, while they might be able to share the same one. (it also prevents from using GPU instancing later on, which is one of the ways to optimize this further).
I would recommend you just scale the sphere
MeshInstance and re-use the same sphere mesh, instead of regenerating it individually. That will be a lot cheaper.
I’m not a expert in physics engine internals, but my assumption is that the physics engine works best when the shape of objects remain constant. It is usually quite rare to see an object change shape in a game involving physics.
If the shape changes size, it means the physics engine has to recompute how that shape sits within the physics world, entirely. That means recomputing its location in the tree data structures, checking if it overlaps with anything else, and other things which I’m not aware of.
While changing the collision sphere is probably less costly than the graphics, I would recommend you don’t change it every frame, but maybe once per second, if it’s slow enough.
Note: optimizing with servers still has nothing to do with this
Awesome! Makes sense =). Thanks for explaining! And yes, it’s a
SphereMesh I’m using.
I would recommend you just scale the sphere MeshInstance and re-use the same sphere mesh, instead of regenerating it individually. That will be a lot cheaper.
How would I go about doing that? Should I create one mesh instance in the meta-code (outside of the Cell class) such as
visualmesh = SphereMesh.new(), and then pass it to each Cell instance? I don’t understand why then scaling the mesh in each Cell would not change the scale on the only mesh instance that exists (
I’m also having troubles finding a
scale() for the
SphereMesh in the documentation for it and all the classes it inherits. How do I scale the
Response note: good to know it has nothing to do with the servers =). I mentioned it in case it had something to do with using the servers directly. I was guessing that the problem was that the mesh and shapes should be spawned in the servers somehow (e.g. using
toblin | 2020-04-29 07:14
Ok, I so a
MeshInstance can be scaled, but not a
SphereMesh. Since I’ll be dealing with thousands of instances, I’m wondering if it’s not better to use a
MultiMesh? My requirement is however that each mesh instance be individually scalable. I’ve asked the question of how to do so using a
MultiMesh, and whether or not it is possible, here.
toblin | 2020-04-29 08:35
Ok, so I think I answered my own question of how to scale the mesh instances of a
MultiMesh. I did so here.
toblin | 2020-04-29 10:12
Should I create one mesh instance in the meta-code (outside of the Cell class) such as visualmesh = SphereMesh.new(), and then pass it to each Cell instance?
Yeah, I guess. Or just load it from a resource and assign it. That mesh should never need to change, really. Unless you want some of your cells to become cubes.
I’m also having troubles finding a scale() for the SphereMesh in the documentation for it and all the classes it inherits. How do I scale the SphereMesh?
a MeshInstance can be scaled, but not a SphereMesh
Really, don’t scale the
SphereMesh, that’s the whole point in my answer.
SphereMesh is just the data that composes the sphere, the drawn size should be decided only using the scale of the
MultiMeshInstance transforms. Scale properties on the instances is what makes this cheaper because it will happen on the GPU.
I don’t understand why then scaling the mesh in each Cell would not change the scale on the only mesh instance that exists (visualmesh).
I don’t understand what you describe. Just give each cell a
MeshInstance using the same
SphereMesh, and scale the instances. Or use a multimesh. Also make sure the visual node is not the root of the cell, because the physic node should not be scaled. It’s a matter of picking different strategies for visuals and physics.
Zylann | 2020-04-29 17:18
@Zylann, I appreciate your persistence in this question =). This is what I’ve done: I’ve used a
MultiMesh with a
SphereMesh as its mesh:
multimeshinstance = MultiMeshInstance.new()
multimeshinstance.multimesh = MultiMesh.new()
multimeshinstance.multimesh.transform_format = MultiMesh.TRANSFORM_3D
multimeshinstance.multimesh.mesh = SphereMesh.new()
multimeshinstance.multimesh.mesh.radial_segments = 8
multimeshinstance.multimesh.mesh.rings = 8
multimeshinstance.multimesh.instance_count = MULTIMESH_NUMBER_OF_INSTANCES
multimeshinstance.multimesh.visible_instance_count = 0
Then to change the size of the cells, I scale the transform of the multimesh instances:
func set_visualmesh_radius( new_radius ):
visualmesh_radius = new_radius
var visualmesh_transform = multimesh.get_instance_transform( visualmesh_idx )
visualmesh_transform.basis.x = visualmesh_transform.basis.x.normalized()*new_radius
visualmesh_transform.basis.y = visualmesh_transform.basis.y.normalized()*new_radius
visualmesh_transform.basis.z = visualmesh_transform.basis.z.normalized()*new_radius
multimesh.set_instance_transform( visualmesh_idx, visualmesh_transform)
Doing this, I have seen drastic increases in performance. The setting of radii has gone from taking 10s of seconds to 0.1s of seconds when the ball count goes up high.
Is this method equivalent to the scaling of a
MeshInstance instead of scaling the
SphereMesh as you suggest? I.e. is it efficient?
Also make sure the visual node is not the root of the cell, because the physic node should not be scaled. It’s a matter of picking different strategies for visuals and physics.
This makes sense, but I don’t think there’s much risk in my case. Spawning everything through the servers means that there is no node tree to worry about (except for the
MultiMesh which I’ve added as a child to the
One downside to this method is that I don’t understand how to make instances of the MultiMesh invisible when the cells die. I’ve asked that question here for anyone that’s interested.
toblin | 2020-04-30 06:53
Scaling transforms on a
MultiMeshInstance is probably the fastest alternative yeah. Only downside being, One cell is no longer contained within a single scene, visuals are shared within a
MultiMeshInstance. Btw, you may want to have a look at this video: https://www.youtube.com/watch?v=pmyOYInhlkI
Zylann | 2020-04-30 12:08