2
\$\begingroup\$

We are developing a 2D game in Godot and we are stuck while trying to divide the map in chunks. Namely, the scene is a forest, where trees spawn positions were generated by noise: since the trees are too many to be loaded altogether, we created a Chunk node, which only instances trees contained in it, and gets instanced and deinstanced according to player's position. Though, this does not seem to be enough: each time a new chunk is to be instanced, we get a lag spike. How can we improve this? This is the script attached to Chunk:

extends Node2D

var noise

func _ready():
    randomize()
    self.name=str(global_position)
    noise=get_node("/root/global").noise
    LoadTrees()

func LoadTrees():
    var x=-38
    while x<39:
        var y=-14
        while y<15:
            if noise.get_noise_2d(global_position.x+float(10*x),global_position.y+float(12*y))>0.07:
                InstanceTree(Vector2(10*x+rng.randi_range(-3,3),12*y+rng.randi_range(-3,3)),self)
            y+=1
        x+=1

func _on_Exit_body_exited(body):
    if body.name=="Player":
        call_deferred("free")


func _on_AreaLeft_body_entered(body):
    if body.name=="Player":
        var NewChunkPos=global_position-2*Vector2(380,0)
        get_parent().InstanceChunk(NewChunkPos)

func _on_AreaRight_body_entered(body):
    if body.name=="Player":
        var NewChunkPos=global_position+2*Vector2(380,0)
        get_parent().InstanceChunk(NewChunkPos)

func _on_AreaDown_body_entered(body):
    if body.name=="Player":
        var NewChunkPos=global_position+2*Vector2(0,170)
        get_parent().InstanceChunk(NewChunkPos)

func _on_AreaUp_body_entered(body):
    if body.name=="Player":
        var NewChunkPos=global_position-2*Vector2(0,170)
        get_parent().InstanceChunk(NewChunkPos)

The functions the script calls from its parent's script go as follows:

func InstanceTree(pos,Parent):
    var tree=Tree.instance()
    tree.position=pos
    tree.name=str(global_position)+"_tree_"+str(pos)
    Parent.call_deferred("add_child",tree)

func InstanceChunk(NewChunkPos):
    if not self.has_node(str(NewChunkPos)):
        var NewChunk=Chunk.instance()
        NewChunk.global_position=NewChunkPos
        NewChunk.name=str(NewChunkPos)
        call_deferred("add_child",NewChunk)

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

I can think of a few options:

  1. Since the tree count doesn't change, you could try making a scene with all of the trees already loaded, then just reposition them all when you load the scene.

  2. Use the yield capability of GDScript. I've never used it, so I'm not sure if it would meet your needs.

  3. Load the scene a bit earlier (before it's fully visible), and add a tree each frame until the scene is full.

  4. If it's a single-player game, you can have a fixed number of trees, and just reposition them around the player instead of constantly needing to instantiate them. This allows you to do away with the chunking altogether.

\$\endgroup\$
0
\$\begingroup\$

If you are rendering many instances of the same mesh, consider using a MultiMeshInstance:

MultiMeshInstance is a specialized node to instance GeometryInstances based on a MultiMesh resource.

This is useful to optimize the rendering of a high amount of instances of a given mesh (for example trees in a forest or grass strands).

\$\endgroup\$
1
  • \$\begingroup\$ I forgot to specify this, but our game is a 2D one, while MultiMeshInstance seems to be indicated for 3D games, if I am not wrong. \$\endgroup\$ Commented Sep 14, 2019 at 14:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .