cleaning up

Is there a way to completely unload a model?
I know about detach() I know about remove(), but none of these seem to really have much effect, not for a long shot.
I am writing a space shooter, meaning a lot of weapons fire and effects (mostly on the form of animated sprites/texture cards).
And the whole effects seem to slow down the frame rate after some time permanently, even when removing them with the mentioned commands.

I know, I could just use a limited pool of sprites and effects for this, reusing them when needed. which would solve that problem.
But my game won’t be single player, in fact it will be purely multiplayer. That means a server would need to have every map loaded all the time, which essentially is a waste of memory. This goes for ship models as well.

so I really need to free up memory by cleanly and absolutely unloading models.

The script below creates a new NodePath with one triangle each frame (using GeomVertexWriter method), and remove it again in the next frame using NodePath.removeNode( ). The triangles are created with one random point, so Panda3D can’t reuse the old mesh data.

On my PC (Windows, Panda3D 1.4.2 as distributed) the memory usage stays constant after a few seconds. So it seems the unused models are unloaded completely by Panda3D.

I think you have a memory problem somewhere else. There are dozens of ways to shoot yourself in your own foot using Python (even using Python :-), for example by creating cyclic references. Could you provide a (small) example where you constantly re-create your models, and where memory usage rises?

enn0x

import direct.directbase.DirectStart

from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import Geom
from pandac.PandaModules import GeomNode
from pandac.PandaModules import GeomTriangles
from pandac.PandaModules import GeomVertexFormat
from pandac.PandaModules import GeomVertexData
from pandac.PandaModules import GeomVertexWriter

import sys
import random

class World( DirectObject ):

    def __init__( self ):
        base.toggleWireframe( )
        self.accept( 'escape', self.exit )
        taskMgr.add( self.update, 'update' )
        self.np = None

    def exit( self ):
        sys.exit( 1 )

    def update( self, task ):
        if self.np: self.np.removeNode( )

        self.np = self.createTriangle( )
        self.np.reparentTo( render )
        self.np.setPos( -0.5, 3.0, -0.5 )

        return task.cont

    def createTriangle( self ):
        format = GeomVertexFormat.getV3( )
        data = GeomVertexData( 'name', format, Geom.UHStatic )
        vertex = GeomVertexWriter( data, 'vertex' )

        x = random.random( )
        y = random.random( )
        z = random.random( )

        vertex.addData3f( 0, 0, 0 )
        vertex.addData3f( 1, 0, 0 )
        vertex.addData3f( x, y, z )

        prim = GeomTriangles( Geom.UHStatic )
        prim.addNextVertices( 3 )
        prim.closePrimitive( )

        geom = Geom( data )
        geom.addPrimitive( prim )

        node = GeomNode( 'gnode' )
        node.addGeom( geom )

        return render.attachNewNode( node )

world = World( )
run( )