Removing child objects of loaded gltf model from memory

I seem to be having issues trying to figure out how to remove objects from a loaded gltf model. What I’m doing is loading in a gltf file that contains many variations of different character meshes/materials and saving this as a “generatorModel”. Then for each character in a list I am cloning this “generatorModel” and removing (or setting visible = false at the moment as I’m unable to figure out how to completely remove the model) all models that are not required for this particular instance of a character.

The code that I’m using to do this is shown below. The commented lines are what I have attempted (in varying combinations) which do not seem to have an effect. I can post all of the code if the below is not enough for someone to see what I’m doing wrong, but it’s 300 lines and I didn’t want to add unnecessary bloat to this post.

So my question I suppose becomes, how do you remove particular objects from a loaded gltf scene completely from memory?

// for reference
// generatorModel = gltf.scene;
// clientCharacters[key].model = THREE.SkeletonUtils.clone(generatorModel);

clientCharacters[key].model.traverse(child => {
   
   // remove all objects that are not in the whitelist or a body, head, weapon for this character
   if(!child.name.includes("Bip001") && !child.name.includes("container") && !child.name.includes("CONTAINER")
   	&& child.name !== clientCharacters[key].body && child.name !== clientCharacters[key].head
   	&& child.name !== clientCharacters[key].weapon && child.name !== "Scene"
   	&& child.name !== clientCharacters[key].model.name)
   {
   	console.log(child.name);
   	//child.geometry.dispose();
   	//child.material.dispose();
   	//child.remove();
   	//renderer.renderLists.dispose();
   	//child.parent.remove();
   	child.visible = false;
   }
   
});

example

removePart = character.model.getObjectByName('Cube004_6');
let parent = removePart.parent;
parent.remove(removePart);

cc https://discourse.threejs.org/t/load-change-and-remove-parts-of-loaded-gltf-by-name-from-scene-in-three-js/11241/2

All objects are parented to the same “armature” object, removing the parent breaks everything >_< lol.

EDIT. Alright, I was looking at that incorrectly ^^ seems to be doing the same thing as .removeFromParent(), which for some reason is breaking my code. Very possible I have something strange going on here. Going to take a deep dive to see what might be causing .removeFromParent() (and code provided by 6Inw9) to be throwing me Uncaught (in promise) TypeError: e[i] is undefined.

Knowing that that is the proper way to remove an object is helpful! Greatly appreciated :slight_smile:

After some more research it appears that my error might be that I’m attempting to remove children inside of the traverse callback which the documentation states should not modify the scene graph. Therefore currently looking into ways I can accomplish my goal without having to have a pre-computed list of object names that require removal.

EDIT
The above assumption that the issue was related to removing the children within the traverse method was corret. Resolved this by doing the below:

// loop through all objects for this character
let childObjects = [];
clientCharacters[key].model.traverse(child => {
	
	// add all objects that are not in the whitelist or a body, head, weapon for removal
	if(!child.name.includes("Bip001") && !child.name.includes("container") && !child.name.includes("CONTAINER")
		&& child.name !== clientCharacters[key].body && child.name !== clientCharacters[key].head
		&& child.name !== clientCharacters[key].weapon && child.name !== "Scene"
		&& child.name !== clientCharacters[key].model.name)
	{
		childObjects.push(child);
	}
	
});


for(co in childObjects)
{
	// commented blocks don't seem to be necessary?
	//childObjects[co].geometry.dispose();
	//childObjects[co].material.dispose();
	childObjects[co].removeFromParent();
	//renderer.renderLists.dispose();
}

Had attempted to post this in a reply but it was flagged, just want to let anyone who sees this know what the solution was.

Alright. Got it figured out. It did indeed appear to be because I was attempting to remove within the traverse callback. The below code is what I wound up with. I do have one final question though if someone might be so kind as to answer…the commented blocks in my for loop…don’t appear to have any effect on memory consumption, does that mean that removeFromParent() is removing the geometry and material of this object from memory (if so that’s exactly what I’m wanting to happen)?

// loop through all objects for this character
let childObjects = [];
clientCharacters[key].model.traverse(child => {
	
	// add all objects that are not in the whitelist or a body, head, weapon for removal
	if(!child.name.includes("Bip001") && !child.name.includes("container") && !child.name.includes("CONTAINER")
		&& child.name !== clientCharacters[key].body && child.name !== clientCharacters[key].head
		&& child.name !== clientCharacters[key].weapon && child.name !== "Scene"
		&& child.name !== clientCharacters[key].model.name)
	{
		childObjects.push(child);
	}
	
});
	
	
for(co in childObjects)
{
	// commented blocks don't seem to be necessary?
	//childObjects[co].geometry.dispose();
	//childObjects[co].material.dispose();
	childObjects[co].removeFromParent();
	//renderer.renderLists.dispose();
}