Grass breaking frame rate :(

Hello again, I was trying to create a natural-themed game scene, but when I added the grass, the frame-rate plummeted a lot, I think I am problem with the number of objects in the scene. Does anyone know a way to fix this? Am I doing something wrong?

Project made at UPBGE

Download .blend:

Maybe just merge the objects together: Faster to render 1 object with 10K faces than it is to render 10K objects with 1 face.

3 Likes

Use custom LOD (when the player is at a certain distance, turn grass objects invisible & visible when the player is near)

Also set-up occluder objects when possible.

Merge the objects, batch them together or maybe try geometry instancing from material options.
I’m not sure about the latter as it causes an instant CTD on my computer, so I haven’t really tested it

2 Likes

I can’t use this code to group objects added durante o gameplay :frowning:

how i can use “merge(objects)”? I try and no work. (sorry my english)

select a few grass objects and hit ctrl+j

1 Like

i’m try this code, but him return a erro in console: “Error: object “Grass_merge” already used in a batch group”

from bge import logic as g
from bge import types as t
import math
import random

cont = g.getCurrentController()
scene = g.getCurrentScene()
own = cont.owner

mesh = own.meshes[0]


for index in range( mesh.getVertexArrayLength(0) ):
    vertex = mesh.getVertex( 0, index )
    pos = own.worldTransform * vertex.XYZ
    porcentagem = 0.05
    if random.random() < porcentagem:
        lst = scene.addObject("Grass")
        lst.worldPosition = own.worldTransform * vertex.XYZ
        lst.localScale = [random.uniform(0.5, 1.0), random.uniform(0.5, 1.1) ,random.uniform(0.5, 1.1)]
        
        ori = lst.localOrientation.to_euler()
        ori[2] = math.radians(random.uniform(0.0, 360.0))
        lst.localOrientation = ori.to_matrix()
        
        all_grass = [obj for obj in scene.objects if obj.name.startswith("Grass")]
    
        
    print(index, mesh.getVertexArrayLength(0)-1)
    
    if index >= (mesh.getVertexArrayLength(0)-1):
            b_g = t.KX_BatchGroup(all_grass)
            b_g.merge(["Grass_merge"])
            print(scene.objects)

AFAIK initializing a batch group with a list of objects automatically merges them.

from bge.logic import getCurrentController
from bge.types import KX_BatchGroup as bgroup
own = getCurrentController().owner

mesh = own.meshes[0]
all_grass = [None for vi in range( mesh.getVertexArrayLength(0) )]

for vi in range( mesh.getVertexArrayLength(0) ):
    vert = mesh.getVertex(0, vi)
    newObj = all_grass[vi] = own.scene.addObject("Grass")    
    newObj.worldPosition = own.worldPosition + vert.getXYZ()

#make sure no item in the list equals None, then make the batch
all_grass = [obj for obj in all_grass if obj]
batch_grass = bgroup(all_grass)

Here’s my test file grass.blend (956.7 KB)

1 Like