Help with Optimisation - Logic Bottleneck

Goooood morning everyone. Zaoshang hao.

I’ve been building a very python heavy, random generating script for a 2D game I’ve been making and I need a lot of help optimising it because even on my i5 2320 (I believe) it lags in the logic sometimes, not all the time, but when levels are stretched out to 60 seconds (as they will be in the final version) some levels have logic spikes that just keep building, as if more and more objects with logic are being created and not removed. What I think might be the problem is that in my setup: Each bomber ship launches a bomb at random intervals (+1 random generation per logic tic), each bomb leaves a trail of specs that EACH generate 2 random integers (+2 random generations per logic tic per contrail object), each missile fired from the player does the same thing every 5 tics or so, and so on.

I remember a test being run by one of us here in the forums on loops vs per object logic. Being that, ONE script would loop through all objects with a property and affect them individually, instead of each object running it’s own script. Which I believe might be the solution to my problem.

Or perhaps, upon your own inspection, you can come up with far better solutions.

No matter what, I very much appreciate your help.

I will link to the .blend file so you may look at the logic and code. And from this file you may use any scripts and ideas regarding logic that you may fancy, however I request that the image files and sounds be reserved for myself. (Also bare in mind that I have changed “Player.py” to facilitate the idea of debugging, what happens to the level progression is purely for the purposes of fixing the game and does not represent the final system.)

Thankyou for your time, and your help.

TomCat

// 1.6 mb
// 2 windows will open, however all you need will be in the first window
// Any criticisms welcome, optimisation in mind
// .blend

Thankyou, xie xie, gracias, origato, merci, danke, kiitos.

Can no-one help?

Please, it’s driving me mad. 6.46ms on logic is ludicrous.


i tried it , i have problem with graphyc , i see all blank (white) already in edit mode , but also in game.
switcing in wireframe mode it work well, i not see any lag.

the logic go at 0.8/1.2ms (i have a cpu of 3Ghz , not special)

boh?

Your player script is very long (300 lines + ), trying to divide it into many different scripts/modules/classes may be helpful, also try not to use that many near sensors, my own experience are telling me that using many of this will slow down the game (I may be wrong here, so please correct me if so). if it is possible try to use getDistanceTo(other) to check if the player is near anything. you can also try to upgrade your version of blender, I where using 2.69 and i had rly no big problem whit any lag when I ran your game. (using an i5 processor )

One technique you can try is to disable most parts of the game and then add them back in a bit at a time and try to find when the spikes start happening.

If I had to guess, I think your problem is caused by having a lot of Near and Ray sensors in your scene at the same time.

I have an AMD FX6100 @4ghz (not much faster than your i5) and I get 0.15ms for the logic…? Also, I think you need to pack your textures. I would recommend that rather than using so many faces per object, you should rather just use a plane with an alpha texture. This will improve performance in a few areas.

I found… the problem… phew.

“trying to divide it into many different scripts/modules/classes may be helpful” - Absolutely correct, thank you so much.

The new code has been improved from:


    if not "missile_s" in own:
        own["missile_s"] = False
    
    if not "Missile_timer" in own:
        own["Missile_timer"] = 0
    
    if not "Enemy_Tally" in own:
        own["Enemy_Tally"] = 1
    
    if not "Missile" in own:
        own["Missile"] = 0


    if not "ScoreToK" in own:
        own["ScoreToK"] = 0


To:


def init_once():
    if not "Missile" in own:
        own["Missile"] = 0
        
    if not "Shields" in own:
        own["Shields"] = 1500


    if not "Asteroid_timer" in own:
        own["Asteroid_timer"] = 0
    
    if not "enemy_lifetime1" in own:
        own["enemy_lifetime1"] = 360
        # 360
    
    if not "enemy_lifetime2" in own:
        own["enemy_lifetime2"] = 240
        # 240
        
    if not "enemy_lifetime3" in own:
        own["enemy_lifetime3"] = 300
        # 300
    
    if not "missile_s" in own:
        own["missile_s"] = False
    
    if not "Missile_timer" in own:
        own["Missile_timer"] = 0
    
    if not "Enemy_Tally" in own:
        own["Enemy_Tally"] = 1
    
    if not "Missile" in own:
        own["Missile"] = 0


    if not "ScoreToK" in own:
        own["ScoreToK"] = 0
    
if own["init_run"] == True:    
    print ("Line : 345 // Running module: init_once")
    own["init_run"] = False
    init_once()



Even though I knew that an (if not “x” in own) condition operation every frame was high logic, I had no idea that it would be so slow and taxing. So the fix came as a run once module, so that it lags the start of the runtime for a tiny bit, and no longer chugs the CPU every single frame.

Thank you guys for your ideas and your help. I’m going to see if I can implement a python replacement to near sensors and ray sensors.

Thank you all,
TomCat

if own[“init_run”] == True:

So where you set “init_run” = True so that this script works? Don’t you need another run-only-once for that?

Why not just add all the properties to the object/object template before starting the engine? That way you don’t have to use init script in this form at all.

If you can’t for some reason, since you’re now checking that you do it only once in the init part, you can just write the init() function like this:


def init():
    own["Missile"] = 0
    own["Shields"] = 1500
    own["Asteroid_timer"]
    ...

if not "init" own:
    init()
    own["init"] = True
    print("Init done")
    #only change the condition AFTER you have run the init() so if 
    #there is error in init() it doesn't proceed and mark the init completed

Half of them already are. Adding all of them in like that makes it really hard to change them later because they’re in a list with their own cluttered UI. Making them in a script lays them out neatly, and makes them easier to change.

For a run once situation, the way I have it now is perfectly acceptable, but I can definitely see why yours would be much better. I just think at the moment the difference in performance would be moot, it’s the only very first frame after all. But thankyou though.