libgdx / box2dlights

Fork of box2dlights by Kalle Hamalainen
Apache License 2.0
256 stars 81 forks source link

Light rayhandler sometimes null causing NullPointerException #48

Closed hard2bit closed 7 years ago

hard2bit commented 9 years ago

Hello again,

I'm having some trouble handling lights creation / destruction on my game. On my game, I create and destroy lights quite frequently (the character shoots bullets with a small light attached). Sometimes, when calling Light.remove(), the system throws an unhandled NullPointerException, like the one below:

03-13 14:45:47.294: E/AndroidRuntime(7099): FATAL EXCEPTION: GLThread 88127
03-13 14:45:47.294: E/AndroidRuntime(7099): Process: package.android, PID: 7099
03-13 14:45:47.294: E/AndroidRuntime(7099): java.lang.NullPointerException: Attempt to read from field 'com.badlogic.gdx.utils.Array box2dLight.RayHandler.lightList' on a null object reference
03-13 14:45:47.294: E/AndroidRuntime(7099):     at box2dLight.Light.remove(Light.java:212)
03-13 14:45:47.294: E/AndroidRuntime(7099):     at package.Globals.removePendingLights(Globals.java:144)
03-13 14:45:47.294: E/AndroidRuntime(7099):     at package.screens.TestScreen.render(TestScreen.java:78)
03-13 14:45:47.294: E/AndroidRuntime(7099):     at com.badlogic.gdx.Game.render(Game.java:46)
03-13 14:45:47.294: E/AndroidRuntime(7099):     at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:422)
03-13 14:45:47.294: E/AndroidRuntime(7099):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1531)
03-13 14:45:47.294: E/AndroidRuntime(7099):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1248)
03-13 14:45:51.344: E/AndroidGraphics(7099): waiting for pause synchronization took too long; assuming deadlock and killing
03-13 14:45:51.344: I/Process(7099): Sending signal. PID: 7099 SIG: 9

The way I'm handling lights removal is the same as bodies removal; in the main loop:

@Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        tweenManager.update(delta);

        worldStep(delta);
        player.removePendingBodies();
        player.getWeapon().removePendingBullets();
        Globals.removePendingLights();
       (...)
   }

The bad thing is this only happens sometimes, quite randomly (I haven't found any crash pattern yet). Any idea why this could be happening?

rinold commented 9 years ago

This might happen cause of rayHandler is not thread-safe, but don't know why this really happens :( However, I suggest you (and this might fix your issue) to use pooling - that was created in libgdx for temporary objects like bullets. Destruction and especially creation of lights, as well as bodies afaik, is not very good from performance and memory side. Try to use pooling and just activate/deactivate pooled lights and reattach them to correct bullet bodies.

haimat commented 9 years ago

I can confirm that using pooling the handling of box2dlights works fine. We re-use dozens of lights each second, that works perfectly well via pools.