Clean way to destroy a body will all its shapes

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
Marty
Citizen
Posts: 89
Joined: Mon Dec 04, 2017 1:47 am
Location: Germany

Clean way to destroy a body will all its shapes

Post by Marty »

Hi dear löve fellows, I need a quick clarification when it comes to destroying bodys with all its shapes. How is it done without memory leaks?

Back in 2011 there was an issue due to collisions that was fixed: https://love2d.org/forums/viewtopic.php?f=4&t=2565
From the thread I can clearly see that people intended to destroying the shapes by hand before destroying the body. The documentation also states that body:destroy "explicitly destroys the Body and all fixtures and joints attached to it", so no shapes. In conclusion I assume I have to remove all my shapes by myself like this:

Code: Select all

destroy = function(b)
	for i, fixture in pairs(b:getFixtureList()) do
		local shape = fixture:getShape();
		shape:destroy()
	end
	b:destroy()
end
However, shape:destroy() was removed in 0.8.0. Could it be that body:destroy() was changed, so it removes the shapes, too? (If so, documentation should be updated.)
Visual Studio Code TemplateRichLÖVE Mobile (AdMob+UnityAds+PlayGamesServices+GameCenter)Add me on Discord

───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░░░░░░░░█────
▄▄──█░░░▀█▀░░░█──▄▄
█░░█▀▄░░░░░░░▄▀█░░█
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Clean way to destroy a body will all its shapes

Post by ivan »

First all there is a difference between shapes and fixtures in the newer versions of Box2D.
One shape could be shared along many fixtures or bodies - that's why there is no "shape:destroy()".
You don't need to destroy the shapes yourself (nor should you want to),
Lua's garbage collector should be able to pick that up automatically.
User avatar
erasio
Party member
Posts: 118
Joined: Wed Mar 15, 2017 8:52 am
Location: Germany

Re: Clean way to destroy a body will all its shapes

Post by erasio »

It's noteworthy that this has been solved in a slightly different way in love than it is in box2d itself.

If you look at the documentation for newFixture:
Note that the Shape object is copied rather than kept as a reference when the Fixture is created. To get the Shape object that the Fixture owns, use Fixture:getShape.
This means the bug and issue from 2011 has been resolved by getting rid of shape references (and that box2d functionality).

Each fixture has their own shape. Destroying a fixture therefore means destroying the shape because you have no reference to that shape in lua. (Not 100% sure how Fixture:getShape() plays with this but as long as you don't store a reference to that fixture owned shape explicitly it should be irrelevant and I'd hope it creates a weak reference).
User avatar
Marty
Citizen
Posts: 89
Joined: Mon Dec 04, 2017 1:47 am
Location: Germany

Re: Clean way to destroy a body will all its shapes

Post by Marty »

erasio wrote: Sat Dec 09, 2017 9:26 am It's noteworthy that this has been solved in a slightly different way in love than it is in box2d itself.

If you look at the documentation for newFixture:
Note that the Shape object is copied rather than kept as a reference when the Fixture is created. To get the Shape object that the Fixture owns, use Fixture:getShape.
This means the bug and issue from 2011 has been resolved by getting rid of shape references (and that box2d functionality).

Each fixture has their own shape. Destroying a fixture therefore means destroying the shape because you have no reference to that shape in lua. (Not 100% sure how Fixture:getShape() plays with this but as long as you don't store a reference to that fixture owned shape explicitly it should be irrelevant and I'd hope it creates a weak reference).
Interesting. So in the case of using a shape on more than one fixture the shape will be copied by value, not by reference. In that case I see no reason why there should not be a shape:destroy() or why the body:destroy() should not include the shapes of its fixtures. If the latter already happens, someone should update the documentation regarding this.

So in other words, if I make sure there is no hard references to the shapes, the shapes will be destroyed for me? Do I have to tell the garbage collector to start fetching things up for me?
Visual Studio Code TemplateRichLÖVE Mobile (AdMob+UnityAds+PlayGamesServices+GameCenter)Add me on Discord

───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░░░░░░░░█────
▄▄──█░░░▀█▀░░░█──▄▄
█░░█▀▄░░░░░░░▄▀█░░█
User avatar
erasio
Party member
Posts: 118
Joined: Wed Mar 15, 2017 8:52 am
Location: Germany

Re: Clean way to destroy a body will all its shapes

Post by erasio »

modiX wrote: Mon Dec 11, 2017 11:21 am Interesting. So in the case of using a shape on more than one fixture the shape will be copied by value, not by reference. In that case I see no reason why there should not be a shape:destroy() or why the body:destroy() should not include the shapes of its fixtures. If the latter already happens, someone should update the documentation regarding this.

So in other words, if I make sure there is no hard references to the shapes, the shapes will be destroyed for me? Do I have to tell the garbage collector to start fetching things up for me?
You seem obsessed with having other people add tons of explicit documentation while there is already a large amount of documentation available as well as the original box2d docs still existing.

But alright. Let's take a step back and look and what happens and how box2d works.

In box2d. You first need a world. Your physics world. All physics objects will be located within this world.

This happens via bodies. The world has a list of bodies. It does not care for fixtures or shapes. This is the only place references to physics objects are stored. Without body there is no collision.

A shape defines the outline of your physics object. It is essentially pure data, with a few util functions for accessing that data. A shape on it's own is nothing but a bit of occupied ram. A quite tiny bit. A shape is completely ignored by the world itself.

And then we have a fixture. A fixture mounts a shape to a body as well as defines some collision resolution data (e.g. density and friction).

In a very simplified and non accurate way. The world now goes through all bodies, checks all fixtures, gets all shapes and looks if they overlap. If so, it will use the data within the fixture to resolve the collision if appropriate.

This means. As soon as you destroy the body. It does not exist in your world anymore. Once all references to it are removed, the garbage collector will shortly after notice this and clean up everything behind the scenes.

However. Maybe you don't want to destroy the whole body. Since a body can have multiple fixtures, being able to remove a single one is important. Destroying the fixture will unmount the shape from the body. And hence forward only the remaining shapes will be used for collision detection. Once all references are removed, the garbage collector will shortly after notice this and clean up everything behind the scenes.

And now shapes... shapes are nothing. Destroying a shape has to destroy the fixture. Since otherwise it points at nothing and box2d will either crash, throw an error or fix this logic error for you in the best case and destroy the fixture (I haven't looked at the code so I'm not sure which of the 3 things happens).

Destroying a shape could only possibly result in freeing up ram. A shape has no list of fixtures. So without a lot of book keeping behind the scenes, it can not possibly destroy the fixture and you are running into issues.

Like with all userdata (if implemented correctly. Which is the case in love), as soon as it goes out of scope and is collected by the garbage collector the destructor is called, the ram is freed and everything is taken care of.

There is literally no reason to ever explicitly destroy a shape. It's on the same level as wanting to explicitly destroy a number or string. Just with potential to cause issues instead of just freeing ram.

This function doesn't exist to protect you from doing bad things.

Edit: For reference. You can't destroy audio sources either. Nor any other type of userdata. love.physics is special in that regard because it might be necessary to remove things from the system immediately, even if the variable might still exist for a while until the garbage collector clears it.
User avatar
Marty
Citizen
Posts: 89
Joined: Mon Dec 04, 2017 1:47 am
Location: Germany

Re: Clean way to destroy a body will all its shapes

Post by Marty »

Thanks for taking the time explaining me this erasio. I wasn't 100% sure. It's good to know the garbage collector takes care of the shapes, eventually.
erasio wrote: Mon Dec 11, 2017 6:51 pm You seem obsessed with having other people add tons of explicit documentation while there is already a large amount of documentation available as well as the original box2d docs still existing.
Haha you are right, sorry for that, tho. :o:
Visual Studio Code TemplateRichLÖVE Mobile (AdMob+UnityAds+PlayGamesServices+GameCenter)Add me on Discord

───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░░░░░░░░█────
▄▄──█░░░▀█▀░░░█──▄▄
█░░█▀▄░░░░░░░▄▀█░░█
User avatar
erasio
Party member
Posts: 118
Joined: Wed Mar 15, 2017 8:52 am
Location: Germany

Re: Clean way to destroy a body will all its shapes

Post by erasio »

I mean we have wiki docs for a reason. If you have a good idea, an info graphic or something like that, feel free to just add it.

Though having long texts before every function isn't really helping usability. They've been kept intentionally short.
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 68 guests