bbyford

Best way to remove objects from the stage?

Recommended Posts

I'm trying to remove sprites and containers from the current app.stage as to add new ones–e.g. change scene. However, both:

let i = 0;
app.stage.children.forEach(function(child){
  app.stage.removeChild(i);
  i++;
});

and

app.stage.children.forEach(function(child){
  child.destroy(true);
});

remove the top level sprites but not the ones in a container?! Very strange. A second trigger of either of the above then removes them but I'd rather not trigger a function twice without working out why it's not working. I'm running pixi.js - v5.2.0

Share this post


Link to post
Share on other sites

Very strange. 

both of your implementations remove only half objects because you actually modify the collection :) Look at the picture.

Unfortunately, I dont have enough time to explain everythign to people this month, so I can do only general suggestions:

Look at https://github.com/pixijs/pixi.js/tree/dev/packages/display/src

1. I hope you have experience with adding/removing elements in array.

2. You have to read sources of removeChild and removeChildren. 

3. You have to read source of destroy()

4. You have to understand how exactly javascript GC works and why cant we just "remove object".

5. even destroy(true) is different from our "destroy" . Does it handle WebGL textures ? i dont know. Read up on that.

6. WebGL objects need a destroy, everything else needs to be removed from global and local scopes, not more. Why? Need experience with javascript and WebGL to understand that. PixiJS just mirrors it.

Now you can meditate on that and wait when someone with free time can explain you how to delete objects in pixi.

 

jstest.png

Edited by ivan.popelyshev

Share this post


Link to post
Share on other sites

Best way is "stage.removeChildren()" but you might need some extra stuff if you want to manage your Texts differently or Textures - destroying texts is a problem because... well.. i dont have time  to explain, here's one of those threads, you can search more: https://github.com/pixijs/pixi.js/pull/6427

Read up removeChildren() code anyway.

If you use destroy() of all children , do it with backwards iteration, that way you wont trigger the problem you encountered. Or copy the array of children before you iterate through it.

Edited by ivan.popelyshev

Share this post


Link to post
Share on other sites

So I guess the anwser is, there is no best way. I want to kill everything on screen and re build, e.g. move to a new scene... this makes sense for how my mind is viewing the game and how pixi works, and I was hoping that there might be wisdom for a best case, or normal way of proceeding. This not the case then it sounds like someone (maybe me) needs to work it out and write a tutorial and its seems pretty basic to want to add and remove sprites and containers without them lingering on screen or having to do strange hacky things.

Share this post


Link to post
Share on other sites

Oh, its a new scene problem!

Then you have a few options :)

1. Destroy all textures and re-load all the assets

2. Dont destroy textures, dont pass "texture:true" in recursive destroy. - in that case you share assets between two scenes

3. Some textures are shared some are not.. Well.. you have to know how loader and everything else related to assets work to make that work :)

Lets think about 2)

Instead of going through those If's , why not just make scene a child of stage?

stage.addChild(scene)

...

scene.destroy({
   children: true
}); // destroy only texts textures and containers/children . All referenced textures are alive!
// now scene does not exists even in stage.

IF you dont want to do that, well, you can destroy() whole stage and recreate it with "app.stage = new PIXI.Container()" - its fine.

Or you can use those FOR's but just regular FOR with backwards iterator

for (let i=children.length-1;i>=0;i--) {
   children[i].destroy({children:true});
}

and {children:true} is the same as "true" in that case. Now I remembered it :)

You misunderstood Ivan anwser I think.

VVV

yeah, I just posted all the data i know instead of thinking about user problem, it happens

Edited by ivan.popelyshev

Share this post


Link to post
Share on other sites

You misunderstood Ivan anwser I think.

TLDR

while(app.stage.children[0]) {
    app.stage.removeChild(app.stage.children[0])
}


Problem with your code is that your remove element at a specific index during iteration, so you don't remove all elements.

I think app.stage.removeChild() withotut parameter is equivalent to app.stage.removeChild(app.stage.children[0]), but can't check right now.

Share this post


Link to post
Share on other sites

Hi!

I'm going to try to explain my way. I have a simple scene:  Background (PIXI.Sprite), static images (PIXI.Sprite, PIXI.Container, etc) and animations (PIXI.extras.AnimatedSprite).

// Background
stage.addChild(new PIXI.Sprite(Texture.....)); // I dont want to remove never.

// Animations, I save my animations in a array:
this.arrayAnimations = [];

let animation1 = new PIXI.extras.AnimatedSprite(...);
let animation2 = new PIXI.extras.AnimatedSprite(...);
let animation3 = new PIXI.extras.AnimatedSprite(...);

stage.addChild( animation1 );
stage.addChild( animation2 );
stage.addChild( animation3 );

this.arrayAnimations.push(animation1);
this.arrayAnimations.push(animation2);
this.arrayAnimations.push(animation3);


// I can to access to animations via array
this.arrayAnimations[0].play()
this.arrayAnimations[0].position / scale

// And I can remove it

stage.removeChild( this.arrayAnimation[0] ); // in this moment is out from stage but it's in my array to use in another place.

// Later, I can destroy the animation

this.arrayAnimations[0].destroy();
this.arrayAnimations[0] = null;

Share this post


Link to post
Share on other sites
On 2/25/2020 at 10:18 AM, rtalon said:

Hi!

I'm going to try to explain my way. I have a simple scene:  Background (PIXI.Sprite), static images (PIXI.Sprite, PIXI.Container, etc) and animations (PIXI.extras.AnimatedSprite).

// Background
stage.addChild(new PIXI.Sprite(Texture.....)); // I dont want to remove never.

// Animations, I save my animations in a array:
this.arrayAnimations = [];

let animation1 = new PIXI.extras.AnimatedSprite(...);
let animation2 = new PIXI.extras.AnimatedSprite(...);
let animation3 = new PIXI.extras.AnimatedSprite(...);

stage.addChild( animation1 );
stage.addChild( animation2 );
stage.addChild( animation3 );

this.arrayAnimations.push(animation1);
this.arrayAnimations.push(animation2);
this.arrayAnimations.push(animation3);


// I can to access to animations via array
this.arrayAnimations[0].play()
this.arrayAnimations[0].position / scale

// And I can remove it

stage.removeChild( this.arrayAnimation[0] ); // in this moment is out from stage but it's in my array to use in another place.

// Later, I can destroy the animation

this.arrayAnimations[0].destroy();
this.arrayAnimations[0] = null;

this is great, thanks for the example. I will want to do something similar as I'll be adding and removing from the stage but reusing again later so not destroying.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.