bbyford Posted February 24, 2020 Share Posted February 24, 2020 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 Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted February 24, 2020 Share Posted February 24, 2020 (edited) > 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. Edited February 24, 2020 by ivan.popelyshev Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted February 24, 2020 Share Posted February 24, 2020 (edited) 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 February 24, 2020 by ivan.popelyshev bbyford 1 Quote Link to comment Share on other sites More sharing options...
bbyford Posted February 24, 2020 Author Share Posted February 24, 2020 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. Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted February 24, 2020 Share Posted February 24, 2020 (edited) 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 February 24, 2020 by ivan.popelyshev bbyford 1 Quote Link to comment Share on other sites More sharing options...
Velith Posted February 24, 2020 Share Posted February 24, 2020 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. Quote Link to comment Share on other sites More sharing options...
rtalon Posted February 25, 2020 Share Posted February 25, 2020 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; bbyford 1 Quote Link to comment Share on other sites More sharing options...
bbyford Posted March 2, 2020 Author Share Posted March 2, 2020 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. ivan.popelyshev 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.