This site requires JavaScript, please enable it in your browser!
Greenfoot back

IllegalStateException: Actor is not in world

The 'Actor is not in world' exception can occur when your code tries to do something which depends on the location of an actor, after the actor has already been removed from the world. A typical example is:

public void act()
{
    setLocation(getX() - 1, getY());
    if (getOneIntersectingObject(Some.class) != null) {
        getWorld().removeObject(this);
    }
    if (getX() <= 0)  {
        getWorld().removeObject(this);
    }
}

The code above is for a missile which moves from right to left. It should remove itself once it reaches the left edge of the world, or if it hits something along the way. The problem is that the first 'removeObject' call (5th line); if this gets executed, then the actor is no longer in the world. But, the act() method doesn't stop just because the actor has been removed! It then goes on to the following statement:

if (getX() <= 0) {

This calls 'getX()' which asks for the actor's location in the world. However, once the actor has been removed, this is no longer valid!

So, how can you avoid this problem? One easy way is just 'return' from the act() method as soon as you remove the object. To modify the above example:

public void act()
{
    setLocation(getX() - 1, getY());
    if (getOneIntersectingObject(Some.class) != null) {
        getWorld().removeObject(this);
        return;
    }
    if (getX() <= 0)  {
        getWorld().removeObject(this);
        return;
    }
}

Now, your program returns from the act method once the actor has been removed, and no longer tries to do anything that depends on the actor's location.

Another way to solve the problem is to check that the actor is in the world before calling any method which requires the actor to be in the world. You can do this by calling getWorld() and checking that the result is not null. For example:

public void act()
{
    setLocation(getX() - 1, getY());
    if (getOneIntersectingObject(Some.class) != null) {
        getWorld().removeObject(this);
    }
    if (getWorld() != null && getX() <= 0)  {
        getWorld().removeObject(this);
    }
}
An advantage over the first way is that it works in methods other than the act() method.