How to workaround Destroy(component) put before AddComponent running after AddComponent

The gameobject has a rigidbody on it. I run this code.

Destroy(gameObject.GetComponent<Rigidbody>());
gameObject.AddComponent<ConfigurableJoint>();

It returns the error “Can’t remove Rigidbody because ConfigurableJoint depends on it”

I understand that Destroy removes at the end of the frame, and that destroyimmediate is advised to not be used. How would I be able to bypass this? Is destroyimmediate safe enough for removing components?

Also, please don’t give advise on how to reset a rigidbody or something as this was just an example.

I would also prefer an answer that doesn’t involve waiting a frame before adding the component (such as ustilizing yield return new waitforendofframe). However, destroy immediate is probably my only option, in which case is it safe?

Edit - I know configurable joints need rigidbodies. I want a rigidbodie on my object, but think of this as a way to reset the rigidbody. However, please don’t give answers that involve resetting components as this is just an example. The answer I want is for the question of how to remove and readd a component in the same frame without destroyimmediate, or if you need destroyimmediate, is it safe to use that method for components.

You can’t have a joint without a ridgidbody. So this can’t be done. Perhaps a use case as to why you want to do this would help provide a better solution.

If what you’re trying to do had worked, the AddComponent would just add a new rigidbody. So there’s nothing to work around.

Configurable joints are components that makes an attached rigidbody move in different ways, and are meaningless without rigidbodies, so your error message makes sense.

1 Like

I edited my post just to make things more clear. The line in my original post “Also, please don’t give advise on how to reset a rigidbody or something as this was just an example” was implying this was a way to reset the rigidbody.
I understand you need a rigidbody… I want a rigidbody. However, let’s say I have a rigidbody already on my object, but I just want to reset it by destroying and replacing. I can’t do this in the same frame with destroy as I get the error. Is the only way to do this is to use destroyimmediate, and if so, although we are warned not to use it, is it safe to do so if its just for components.

If you just want to ‘reset’ the RigidBody then something like this might work.

rigidbody.velocity = Vector3.zero;

rigidbody.angularVelocity = Vector3.zero;

rigidbody.inertiaTensorRotation = Quaternion.identity;

rigidbody.inertiaTensor = Vector3.zero;

^_~
Thanks anyways ^^

1 Like

If you really want to do this, DestroyImmediate should be fine. You’re adviced not to use it, so you never know what problems will crop up, but this code gives you a rigidbody with the standard values:

DestroyImmediate(GetComponent<Rigidbody>());
gameObject.AddComponent<ConfigurableJoint>();

When I use the code

DestroyImmediate(prefab);
//or
DestroyImmediate(Resources.Load("TestDestroy"));

I get the warning “Destroying assets is not permitted to avoid data loss. If you really want to remove an asset use DestroyImmediate (theObject, true);”
If I add true, then it does delete.

Perhaps DestroyImmediate is not as scary as everyone says? If you are worried about accidentally putting in “true”, then just create a helper method that calls destroyImmediate and doesnt allow you to do “true”. Unless if unity goes in one day and secretly just has destroyimmediate start destroying by default again ^_~

Why arent objects destroyed immediately from the start when using destroy? And why did they have to make destroyimmediate so scary and not just have a method to destroy immediately safely?

If you do DestroyImmediate on a prefab, you’ll delete the prefab from the disk, which is why you’re getting that warning.

If you do it to runtime objects, then they’re just destroyed. So it would be fine to do it with a rigidbody on an instantiated gameobjects.

The dangerous part is if you have a method that destroys input objects. Since there’s no differentiation between the type of a prefab object and a runtime object, you might slip up and send in a prefab instead of an instantiated version of that prefab. If that happens, you’ve suddenly destroyed a project file instead of something from play mode.

I’m not sure, but objects are probably not destroyed immideately for performance reasons - there’s a bunch of side effects of destroying, and it’s probably faster to do all of those things in one go instead of one at a time. It might also be that some interaction of the physics engine and the main engine gets wonked hard if a rigidbody or collider dissapears in the middle of a physics or game frame.

Im not sure I understand what you mean by input object. Do you mean something like a public gameobject field in the inspector that you place a prefab in?
And in regards to “you might slip up and send in a prefab instead of an instantiated version of that prefab.”, when trying to destroy a prefab purposely, either by going directly to my resources folder or through a public gameobject field, it returns the error “Destroying assets is not permitted to avoid data loss. If you really want to remove an asset use DestroyImmediate (theObject, true);” and then doesn’t destroy the object. This means that as long as you create a helper method that runs destroyimmediate and always puts false, you should theoretically never accidentally destroy your assets. Which means there is really no danger at all, at least not unless unity just starts deleting by default.
Something like this…

    public static void SafelyDestroyImmediate(UnityEngine.Object obj)
    {
        UnityEngine.Object.DestroyImmediate(obj, false);
    }

And the performance reason seems like it could be true.

Oops! I missed that, sorry! :sweat_smile:

1 Like

Maybe this used to work? But it’s definitely blocked in 2019.3+. I was surprised and disappointed (this page is a top google hit for the topic). It’s sad that RequireComponent never got fixed, still has the same bugs from > 10 years ago :).

Anyway … in 2019 … I had to do:

foreach( Component c in go.getComponents<Component> )
{
if( c is Joint )
  DestroyImmediate( c );
}
DestroyImmediate( rigidBody );

…which did at least work. The annoying quirk was that I was only trying to destroy “all components except a few special ones”. So the above - if embedded in a loop that’s already destroying objects - has to have a magic-null check up front:

if( c == null ) // we already destroyed it when pre-destroying joints
  continue;

…but it does at least work :).