1

I have a 2d array of vectors of pointers to Entities in a game. The array represents a grid of game world to improve performance when detecting collisions. When an entity moves I check if it moves over to another grid-tile (of course) but this is where everything goes to hell. If I move the object in the array when it changes tile CPU goes to 100% instead of 8% and game physics no longer apply.

This is the update function where it stops working:

    for (int i = 0; i < xGridCount; i++)
    {
        for (int j = 0; j < yGridCount; j++)
        {
            for (auto it : grid[i][j])
            {

                it->update(); 


                //update gridpos
                if ((int) it->x/gridSize != i || (int) it->y/gridSize != j)
                {
                    grid[it->x/gridSize][it->y/gridSize].emplace_back(std::move(it));
                }
            }
        }
    }

Declaration of grid array:

std::array<std::array<std::vector<std::shared_ptr<Entity>>, yGridCount>, xGridCount> grid;

The "update gridpos" is where it collapses. If I comment it out everything works as it should.

I have, of course, figured what I could do to fix it and I've thought of using the array only in the collision detection. But the thing about that would be that I would have to keep 2 pointers of every object, one for hit detection and one for updating/rendering and that doesn't sound like a good solution.

Why is it so CPU heavy? And how else could I do it?

4
  • Instead of describing the declaration of grid, please show it. Commented Feb 25, 2015 at 11:12
  • Edited topic to show it @JoachimPileborg Commented Feb 25, 2015 at 11:14
  • What are you trying to accomplish with the emplace_back(std::move(it)) expression? Commented Feb 25, 2015 at 11:32
  • Move it from a position in the grid to another @KristianDuske Commented Feb 25, 2015 at 11:39

1 Answer 1

2
for (auto it : grid[i][j])

it is a shared_ptr, and this produces a copy. Making a gratituous copy of a shared_ptr is a performance loss. (Usually it stands for "iterator", so I'm not sure why you called it it anyway.)

grid[it->x/gridSize][it->y/gridSize].emplace_back(std::move(it));

This moves the shared_ptr it into the vector for new tile, but since it is a copy, it doesn't do anything to the shared_ptr in old one. As a result, it's now in two grid tiles at once.


There seems to be some confusion: std::move (the one-argument version) doesn't move anything; it merely casts the argument to an rvalue to signal "the contents of this object can be moved". The shared_ptr/unique_ptr move constructors essentially move the ownership of the pointee, not the smart pointer object itself. The moved-from smart pointer (which would be in an empty state) will remain in the container it is in until you actually erase it from the container.

Sign up to request clarification or add additional context in comments.

2 Comments

Okay, makes sense. Would changing it to unique_ptr also make sense?
"I'm not sure why you called it it" - because "it" is as good a word as any for "the thing we're dealing with at the moment".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.