Many objects, BGE framerate drop

Hey guys. I’m working on a survival game. The environment consists of a large forest, this entails having a lot of trees. Now my tree is around 3,000 tris and consist of 30 objects. The reason for there being 30 objects is that the tree is choppable, meaning the trunk has chunks that are removed when chopped. The scene is being proceduraly generated, meaning the trees are added in at random upon running the game. I was able to get 85 trees in without a drop in framerate. This is pretty good but I’m afraid it won’t be good enough for the scale I want. 175 trees dropped the framerate by about 20 frames. keep in mind this is just with the trees/ground/player in the scene. I probably would only be able to fit many less trees in with things populating the scene like bushes/rocks/logs etc… taking up their share of cpu/gpu

So my question is, how can I optimize the game aside from the obvious polygon reduction? I’m thinking blender for some reason has problems handling many objects in the scene. for instance, with 1 tree consisting of 30 objects, duplicated throughout the scene at 175 trees, that makes 5,250 separate objects.

so yeah your help would be greatly appreciated. Doesn’t necessarily have to solve my problem to a t, let’s just get a discussion going and maybe you’ll have some ideas to share.

Well, I’m not surprised, that amount of objects is really high.

I’m also working on a survival game, each tree is cuttable, but they are only one object, at the moment of cut the tree, I spawn a group that have 2 sections(lower and upper) and I delete the old tree, It is only for the cutting animation, when the health of the tree is less than 1, I spawn another group that have every logs separate(without delete the lower section). Later of spawn every group, I delete the empty that it use for instancing(It not delete the objects of the group).

This is how the tree file looks:

What i mean is that you don’t need all theese objects at every always, keep the tree as only one object, and spawn the logs when the player is cutting the tree. This is for keep the number of objects low(it’s important), also I think your tree has lot of polygons.

Level. Of. Detail.

carlo, thanks for the advice. Really thankful you shared that. In regards to the tree’s poly count, It could use a bit of reduction, ideally I would only have like 1,000 tris but for the type of tree I’m going for it’s necessary to be a bit higher poly. Kheetor thanks lod was in the back of my mind just wasn’t sure how I would implement it. Going to plan out how I’ll include lod and switching the tree between low/high poly. It makes things a little more difficult when the tree has chunks that get chopped out. It adds a little more to the problem solving equation in ways I didn’t expect. again thanks for the advice guys

Simply, interaction details are not important when the player cannot interact with the object in question. It should be simple enough to use LOD to ensure that remote objects are just single tree meshes.

If you want to ensure a more visually correct implementation, create n numbers of trees which have different arrangements of cut sections. Use hitboxes on the closest detail level to allow the user to cut each section. When that hitbox detects a hit, run whatever logic is required to determine when the segment is deleted, and then replace the tree according to the current sections.

To do this, give the tree properties, such as segment_1 = True, segment_2 = True, …, to represent whether each segment is there.
If you’re familiar with maths, you could even work out the tree mesh to replace it with using a special tree ID:


def update_tree(controller):
    tree = controller.owner

    segments = 6

    tree_id = 0
    for index in range(segments):
        segment_name = "segment_{}".format(index)
        segment_state = tree[segment_name]

        tree_id |= segment_state << index

    tree_name = "tree_{}".format(tree_id) 

    tree.replaceMesh(tree_name, True, False)

This uses bitwise operations to work out a unique ID for each tree segment. The benefit of this is just simple code :slight_smile:
It looks for properties called “segment_0”, “segment_1” all the way to the value of “segments” - 1 (5, by default).

To calculate what the tree name would be for the models, you could run this code on an object, setting the properties manually, and replacing the replaceMesh line with “print(tree_name)”.

To manage the hitboxes, give them a unique material, and add them at the closest detail level. You can determine the hit material from the ray Sensor, I believe.

Wow, thanks agoose. Regarding the code you wrote, I like your general approach and will implement it.

"Simply, interaction details are not important when the player cannot interact with the object in question. It should be simple enough to use LOD to ensure that remote objects are just single tree meshes. "
Thanks for simplifying, put like that the concept is just common sense. I was a bit naive to that.

Probably one of the better game developers out there, then. The most important lesson for game development is that if you never say the words “that’s a good idea” or “perhaps that’s a better solution”, you’ll be limited. Or perhaps that’s a lesson of life!

Of course, many of us will have said the same. If you’re interested, look at my first BlenderArtists.org posts. If ever there was a significant overview of someone’s personal journey, my post history is, I believe, a good one.

Concerning your point, most of game development is just unusual/ alternative approaches to common sense :wink:

Just for a heads up, I’m not sure how comfortable you are with programming at this stage, but the example I posted is just one means to an end, and many might not feel comfortable with the concepts it introduces. As alternatives, you could write out a long list of all the combinations as names (i.e)


a = tree['segment_1']
b = tree['segment_2']
c = ...

if (a and b and not c):
   tree_name = "tree_1"

if (a and not b and c):
    tree_name = "tree_2"

...And so on for all the combinations

You could also create a basic name using the various states:
In this example, I create a name of the tree in the form “yes_no_yes_no” referring to each segment state (if it is present “yes” or deleted “no”). I replace the boolean True/False value with a string using the states dictionary, and then create a _ separated string using a sequence of yes no values with a generator expression (which is roughly equivalent to [states[a], states[b]]) which would be something like [yes, no] (if a was True and b was False)


a = tree['segment_1']
b = tree['segment_2']

states = {True: "yes", False: "no"}

segment_states = [a, b, c, d, e]

tree_id = "_".join(states[x] for x in segment_states)


(this isn’t anything you don’t already know, just thinking out loud and giving an idea of where I am) soon after adopting your approach I ran into the “ok there are a lot of possible ways to chop a tree” so this is what I’m going on so far. so there’s a hit cube parented to the tree in the region of the trunk where chopping will take place this will allow me to use ray.hitNormal to determine which side of the tree the player is chopping. So let’s say the player is standing behind the tree, with each swing of the axe, a chunk of the tree will be removed from the back, the chunk removal doesn’t have to be in the exact location of the impact to look convincing thankfully. So therefore I can have 4 chunks per each side the tree [4 sides to the tree] (chunks being plugs of wood that are removed when chopped 4 is an arbitrary number of chunks per side). so if the player chopped once at the back of the tree, I would replace the tree’s mesh with ex: “tree_back_1” this mesh would have one chunk removed from the back of the tree. the player chops again at the back, now I replace the tree’s mesh with ex: “tree_back_2” this mesh would have two chunks of wood removed and so on. ok easy enough assuming they stay at the back of the tree. The player can still walk around to the front side, the left side, or the right side. And back and forth, chopping away. So with so many combinations I would end up having a lot of meshes for just one tree. This problem sort of reminds me of fuzzy logic https://www.youtube.com/watch?v=r804UF8Ia4c

If there isn’t a way around this I guess I’ll just have to bite the bullet and create all of the combinations. I’ll be looking for ways to make the process less time consuming. FYI I’ve got the rest of the tree system working nicely, tree fall, sound effects etc… It’s just a matter of having the best optimized solution and this whole wood removal problem is my only real set back. I’m not quite up to par with you on python but I do understand the general concepts. Sorry for the long winded reply, if I could competently speek in code like you it would be easier. My programming is never correct until I’ve tested and gone through trial and error so I won’t waste time by posting my theoretical algorithms.

Agoose, I’ve got to mow the lawn before it gets dark here so please follow up and I’ll be back to read it in about an hour or so. You can bet I’ll be thinking this one through while I’m mowing lol

Ideally, you’d have the ability to manually edit mesh geometry in game. We don’t have such an ability, beyond deforming mesh vertex data (such as their positions and normals).

The reason that we’re discussing using permutations of tree types is to circumvent this.

If you had 6 segments to a tree, that’s 6^2 Permutations (with repetition) Or 36 arrangements. If each segment has four sides (which doesn’t seem sensible because you could only chop each side once, you’d have 6 ^ (4 ^ 2) (I believe), which is a lot, if not too many.

The interesting thing is, if you can get away with it, then you could probably avoid creating separate tree models for these smaller details because they’d be too far away, and only worry about whether the entire segment is missing (back to 36 permutations again). When you’re closer up, revert back to using individual objects; deleting them and restoring the approximate main model when you move to the next tree (or trees > 10 m away).

But you could just model the chunks in the mesh, then grab them and scale them down to 0 to “remove” them from the mesh. I implemented a system (BGHelper.Mesh.CMesh.polygon_list; see the example blend file to see it in action) that allows you to deterministically find specific polygons (i.e. the first polygon is always the front-left-bottom-most polygon, and it increases from there forward, rightward, and upward). This could allow you to identify which polygons compose the “plugs” in the mesh, and to “remove” those according to where you’re chopping. After all, the plugs don’t need to “phase out” or anything, right? They just need to be there, and then be gone?

You could also use vertex coloring to identify these plugs and their ordering.

Solar I’m very interested in your idea. Scaling the chunk to 0 would work perfectly. I’d like to know how to interface with the polygons of the tree’s mesh via python. I took a look at your example file and I was getting an error because blender couldn’t find the BGEHelper module. In any case this is by far the best solution I’ve come across and I’d like to get right down to the nuts and bolts of this system.

If you’re happy to modify the mesh geometry, then this is a sensible choice. You will need to use LibNew to create non-identical meshes within the engine. I’m not sure what the performance cost of this would be, nor how it would sit with LOD. Assuming that it works well (you can never be sure with the BGE ;)) then you may still gain performance by displaying such cosmetic changes only at the closer lod levels.

Did you get the BGHelper folder’s Python files? Use SVN (or a GUI SVN tool like TortoiseSVN) to checkout the source BGHelper folder; the blend file should be in the same folder as the other scripts (BGHelper folder). If it works, the polygons will change color in sequence (as the ordering is, again, deterministic). Adding or removing polygons will work as expected, as the polygons are ordered in sequence (and so you can predict which one is the 4th polygon, for example).

I downloaded these files http://gyazo.com/7dfffc3a139ff7b1d933453a2f108aff and put them in the same folder as the example.blend. When I run the game nothing happens and I get the “no module named BGHelper” error

Or, like terraria, just have the tree break into tiny pieces. Sometimes simple and quick beats realism by several lines of code. That’s how I’m going to do it.