Attaching/detaching components that has had simulate physics enabled crashes the editor. Why? How to avoid?
EDIT: More precise description: Destroying an actor that has been attached to a component that has had simulate physics enabled will crash the editor if the parent component is attached to something else or is set to simulate physics after the destroyed actor has been garbage collected.
It’s meant to be a simple pickup system where the player can collect boxes and put them into a basket. Then bring the basket to a collect zone where the boxes are destroyed. I have simplified the above functionality and implemented it in a fresh clean project based on the TopDown template. The below code is found in the TopDownController. No other settings changed.
I just noticed that the mass of the basket keeps increasing on every attachment. It does not decrease on detachment. I have verified that the detached object is no longer attached (get attach parent). And I have verified that there are no components still attached to the basket (Get children components (include all descendants)). So it does get properly detached. But info from the box is still associated with the basket somehow, affecting physics? If this is the case it could explain why it crashes in the physics engine after the box is destroyed. Question is how to break that association.
A possible workaround seems to be to never destroy the box actors. Just move them aside and set actor hidden in game. This stops the crashing. But that mountain of garbage will keep increasing the longer you play. I don’t think it is a viable solution.
I tried this in the FirstPersonTemplate as well and same problem.
It is crashing in UObjectBase method IsValidLowLevel() line 246.
This line reads as following:
if( !ClassPrivate )
If ClassPrivate is a nullptr, then !nullptr will evaluate to true. How can this line throw EXCEPTION_ACCESS_VIOLATION!? If ClassPrivate is something, it will evaluate to false, if it is nothing, it will evaluate to true. How can ClassPrivate be anything else than something or nothing? How can it be an access violation!?
And about the mass… there is some association there still even after the actor has been detached and deleted. If you look at the call stack it is
UpdateMassProperties()
ComputeMassProperties()
which calls
GetSimplePhysicalMaterial()
which calls
IsValidLowLevel()
On an object that is deleted? But first line in IsValidLowLevel() is:
I installed an older version of the engine, 4.20 and recreated everything in a clean fresh TopDown template project. The entirety of the code is as follows:
Spawn box.
Attach box to basket.
Attach basket to player.
Detach basket from player.
Activate simulate physics on basket.
Deactivate simulate physics on basket.
Detach box from basket.
Destroy actor box.
Loop
This very quickly crashes the editor as well. Can’t see the call stack because it says I do not have debugging symbols installed, but I think it is safe to assume it is the same error.
It seems like a very simple thing to do, pickup things, add them together, let them simulate physics when dropped, and delete them after they’ve served their purpose. I can’t possibly be the only one who want such functionality. What am I doing wrong?
Not sure it makes me any wiser…
It is quite clear that the physics engine is trying to access an object that has been destroyed. But I don’t know how to fix it…
Finally some progress! It seems that when the set simulate physics is off, the physics system will not receive any updates on what is happening with the object. E.g. if the object is attached, detached or destroyed. Then when setting simulating physics to on again it is out of sync, explaining the wrong mass property I had, and explaining the crashing when trying to access an object that has been destroyed and garbage collected.
To not become out of sync and crash, ALL attachments, detachments and destroying of actors need to happen when the set simulate physics is on. Not sure how to build my pickup system around this to be honest… It’s a multiplayer game so can’t have lots of physics activated and replicated to clients all the time. But feels like a big step forward.
Creating a socket on the static mesh and attaching the component to the socket, instead of directly component to component, solved the problem.
EDIT: It made the problem much much less common, but it did not solve the problem. After further testing I think the problem might have been that the socket/attachment was on a child component. Attaching to the “main” component, the one that you set simulate physics on/off to, seem to have solved the problem. But since the problem was so uncommon after the socket fix, it is really hard to tell if it is now gone or not with this second fix.
In my situation, it crashes every time when using attach component to component with a socket.
When adding a breakpoint, it didn’t crash.
Adding an isValid on the two components didn’t fix it. Adding a small delay before attaching fixed it. But it looks like an engine bug.
Edit: the delay only fix the crash at attachment, but not onDestroy…