Wahyu
Wahyu

Reputation: 103

safely remove a child with enterframe running

Whenever I try to remove an object/child with enterframe running I always get null reference error. In my particular case, the setup is Battlefield contains a lot of Robot:

  1. A child (Robot) dispatchEvent that it is destroyed
  2. The parent container receives the event and starts removing the child by removeChild and remove the child from an array of Robots.
  3. on enterframe, during a loop to move the robots around, sometimes I would get null reference, so I have to call if (robots[i] == null) continue;

How do you safely remove the child without sprinkling if robot is null all over my enterframe?

one idea I have is to have a list of robots to be removed inside the enterframe that checks whether there is a robot to be removed, and if there is, do the removal there instead of the callback on robot exploded event.

Upvotes: 0

Views: 472

Answers (3)

back2dos
back2dos

Reputation: 15623

Well, for one in haXe the Array actually has a remove-method. You can use that to remove the robots for good. The method also reports of its success, so your code would look something like:

if (robotsArray.remove(explodedRobot)) 
    robotsLayer.removeChild(explodedRobot)

Please note however, the call to remove on the Array should not occur while it is being iterated over, or you most certainly will get weird behavior.

Upvotes: 1

divillysausages
divillysausages

Reputation: 8033

Two things I normally do:

1) Have an active bool in the object getting updated. When you call your destroy() function or whatever to cleanup, set active to false. In the update() function, make a check at the start. if active is false, quit out.

2) Have a removeFromUpdate property that's set to true when you want to delete your object. In your UpdateManager (or whichever calls the update() on your objects) do something like this:

private function _update():void
{
    // update our objects
    var remove:Boolean = false;
    var len:int = this.m_objects.length;
    for( var i:int = 0; i < len; i++ )
    {
        this.m_objects[i].update();
        if( this.m_objects[i].removeFromUpdate )
            remove = true;
    }

    // if we don't have anything to remove, quit
    if( !remove )
        return;

    // we have something to remove, so traverse the array
    // backwards (so we don't have index problems)
    for( i = len - 1; i >= 0; i-- )
    {
        if( this.m_objects[i].removeFromUpdate )
        {
            // you can optionally call the object's destroy() function
            // here

            // splice the array
            this.m_objects.splice( i, 1 );
        }
    }
}

That pretty much works for me. You can optionally have the object's update() function return true if it should be removed if you want to save on a parameter

Upvotes: 1

Josha
Josha

Reputation: 599

I can not post comments yet, so have to do it this way.

Two things I can think off: You say you remove the child from Robots list. So it seems strange that you encounter null values in the list; unless the remove implementation has a mistake?

Is it possible that inside the ENTER_FRAME while going trough the robots, robot instances get removed? If so, it might help if you go trough the list starting at the last index. If an instance gets removed, it will not change the items at lower index.

Something like:

for(var index: int = list.length; index--; ) doSomething(list[index]);

Upvotes: 0

Related Questions