Self destruction of objects(or nodes) when they fall off the scene

Hi there !:grinning:

I am developing a Universe game that spawn spaceship as a character control & spawn rocks …5 rocks randomly in a fixed range every 200 ms I have put my method that makes rocks in the simpleUpdate of the game context & everything works normally until some time the fps began to dropout downto 10 fps I think it’s from building up objects at the end of the scene

The point :- is I want to make these fallen rocks out of the scene to be self destructed to free memory…I have tried making a control to the skymap & attach it as collision shape but it fails

Thank you :blush:!

Can you explain yourself a little more clearly? You say “fallen rocks” but you also mention a space ship which makes me think “zero gravity” where things do not “fall” so I struggle to “see” what you mean.

What are they colliding with in order to disappear?

Can you maybe show a screen shot? A picture says a thousand words.

1 Like

Yeah, is it just a case if “if distance from center > x then destroy”?

Wondering if you are making it more complicated than it needs to be.

1 Like

Each object has its own gravitational force or linear force if you will , spaceship attached to a node & has a character control physics w/o gravity , other planets have zero gravity as well,only rocks have randomly generated gravitational forces w/ fixed ranges

-they do not disappear but you visualize them as if they are disappeared but actually they are out of draw distance of my map!

see this is the ship with spawning rocks of different gravities mainly on (-x axis) :slight_smile:

& this is the rocks fallen out actually its outside of my draw distance not the scene , so i wanna destroy them if they are outside my draw distance "NB: they all have the same node name so if i will really check (if getChildName(“Rock”).getPhyscisLocation()==specificLocation) then detach it will work but it will actually detach new Rocks being spwaned w/ the same node name:

Actually, i have tried to add a quick timer in the simpleUpdate

       private void simpleUpdate(float tpf){

++updateStack;

if(updateStack >= 5500){
updateStack=0;
stateManager.update(tpf);
rootNode.detachChild(rootNode.getChild(“Rock node”));
rootNode.detachChild(rootNode.getChild(“Laser Gun”));
this.getRenderer().clearBuffers(true,true,true);
this.getRenderer().cleanup();
updateStack=0;
}

as for each 5500 ms … all rocks are destoyed to free some memory as this problem appears after 25 mins from running the game indeed but the problem persists

Never ever ever (never ever) call stateManager.update() yourself.

Don’t.

1 Like

…dare I ask, why are you updating the stateManager manually? And why are you manually clearing the buffers? And cleaning it up?

1 Like

Also, don’t do this either.

It’s probably best to not call internal methods that you don’t understand. Just in general.

If you remove something from the scene graph then it’s eventually gone forever. Nothing else needs to be done.

1 Like

Okay I got it but then problem is that this code w/o those internal methods donot work either

Do I need to call System.gc(); or Runtime.getRuntime().gc(); ??

Well, it’s not working with them. So.

If it were me, I’d add System.out.println to verify all of the hundred assumptions being made.

As I read the code, every 5500 frames (some random amount of time), you grab a random node called “Rock node” and a random node called “Laser Gun” and remove them… never checking that you actually found one.

Very fragile.

If you want to remove a spatial after some period of time then you could add a custom control to the spatial that counts time (time -= tpf) and removes the spatial from its parent after some amount of time.

And periodically you should debug your scene to see what’s actually increasing. Could be you are adding other stuff and not thinking about it.

System.out.println() or the debugger will be your best friend.

No. Not at all.

You need to fix your real problems. “GC” and other magic stuff is not your issue. Your code’s logic is your issue.

1 Like

Okay,They are not random nodes , they are indeed attached to the scene !
Is there is an example for the checking method of time tpf the in simpleUpdate ?

time = time + tpf;

Or if you want a countdown:
time = time - tpf;

Where time is some time in seconds.

Not sure how better to explain because I don’t know which part is confusing.

But if you want a SPATIAL to die after a certain amount of TIME then you want to use a CONTROL… (presuming you want to keep treating spatials like game objects at all but that’s a longer and different discussion.)

Bottom line: I’ve written many programs that add remove megabytes of data from a scene at runtime and I never hit frame drop issues or out of memory issues or any of that… because I know what I’m adding and I know what I’m removing.

For example, during the rapid flying this is adding and removing nodes nearly constantly: https://www.youtube.com/watch?v=gHLP1PYUihE

…I never once call GC in the whole thing.

1 Like

The randoms are only the locations & directions of the rocks w/ a fixed range

System.out.println() everything in your scene graph when you update it.

Or use the debugger and set a break point.

It should be obvious what is happening in your code then.

1 Like

rather than using the simpleUpdate method in your main app to handle the destruction of the rocks (or stray laser blasts, once they are a certain distance away from the camera), it may be better to let the rock object handle it’s own destruction. (Object Oriented)
that way you don’t have to keep track and iterate through a huge list of rock objects checking their positions relative to the camera, and you skip the added effort of having to explicitly determine which object to destroy from a pool of many.
this could be done by giving each rock object it’s own control with a distance check or even a lifespan timer, as @pspeed suggested above.

1 Like

Okay , i have used System.out.println() & fpstext to trigger the problem location in my code & it seems that i was calling wrong name in rootNode.detachChild(rootNode.getChild("Rock node")); i think i have fixed most of my problem now after i have matched names of nodes & removed the internal called methods & decreased the update threshold , but the problem persists when the game runs for about 40-60 mins ,i think it needs time to get rid of those rocks…( I have made some changes)

 ++updateStack;
        if(updateStack >= 50){
                    rootNode.detachChild(rootNode.getChild("Rock node"));
                    physics.getPhysicsSpace().remove(rootNode.getChild("Rock node"));

            try {
                        physics.getPhysicsSpace().remove(rootNode.getChild("Laser Gun"));
                        rootNode.detachChild(rootNode.getChild("Laser Gun"));
                        System.gc();
                    }catch (Exception e){
                        e.printStackTrace();
                    }

                updateStack = 0;
        }

inside simpleUpdate , it works efficinetly w/ rocks but w/ laser gun not very well because if the user shoots too much particles ,the detach method wonot handle them all so , i will add a power to the gun shooter to shoot arround 10 particles only per 500 ms for example .

& i have added a small optimization for the physics space , it has decreased the time for the objects to reach out off the site:

        physics.getPhysicsSpace().setWorldMax(new Vector3f(10f,10f,10f));

Anyway , Thanks !

Yes, because you only remove two objects at a time.

…it would be better to make the decay time based and per-object as I’ve said three times now.

1 Like

Add the control below to every rock. It will remove itself from the scene if the time exceeds maxTime or the distance from the spaceShip exceeds maxDistance.

rock.addControl(new RockDecayControl(spaceShip);
public class RockDecayControl extends AbstractControl {
    
    private final Spatial spaceShip;
    
    private final float maxDistance = 10; // 10 world units.
    private final float maxTime = 100; // 100 seconds.
    private float elapsedTime = 0;
    
    public RockDecayControl(Spatial spaceShip) {
        this.spaceShip = spaceShip;
    }

    @Override
    protected void controlUpdate(float tpf) {
        elapsedTime += tpf;
        
        float distance = FastMath.abs(getSpatial().getLocalTranslation().distance(spaceShip.getLocalTranslation()));
        
        if (elapsedTime > maxTime || distance > maxDistance) {
            getSpatial().removeFromParent();
        }
        
    }

    @Override
    protected void controlRender(RenderManager rm, ViewPort vp) {

    }
    
}

2 Likes

Fantastic thank you I will try it :grinning:

1 Like