Prevent adding certain own/built-in components

I have made my own component which conflicts with some Unity built-in components (like Rigidbody conflicts with Rigidbody2D). So I need to be sure that those components will not exist together in the same GameObject. Is there a way to do it? It seems to be easy to check when my own component added (by Reset() message), but what to do if Unity’ built-in component is added? Is there some callback, message, or event sent when a new component is attached to the GameObject?

Use namespaces so there’s no name collision.

Conflict is not in names, but in behavior.

This seems to happen in C+±land. AddComponent calls Internal_AddComponentWithType, which is an extern method. So there’s nothing exposed for you to do the same thing in user scripts.

You can hack it with Reset. Unity - Scripting API: MonoBehaviour.Reset()

Reset gets called when a component is first added, so you can do a scan there for conflicting classes, and deal with it appropriately.

2 Likes

You could have your Script derive from the built-in incompatible component. If its a component that doesn’t allow for duplicate behavioral types/Subtypes (like RigidBody or Graphic) those classes will typically have a [DisallowMultipleComponent] attribute. By deriving from these classes the unity editor will actively prevent you from adding another type or subtype of that class to the gameobject.

1 Like

Through it I can’t handle when Unity built-in components added.

Via reflection? Both RigidBody and RigidBody2D are sealed.

public sealed class Rigidbody : Component
public sealed class Rigidbody2D : Component

Also deriving from them is irrational due to the fact that behaviour of my component is totally differs (my component acts like Transform and defines own transformation rules about which RigidBody does not know)

You could use a custom inspector to do this, then. In OnInspectorGUI, call DrawDefaultInspector() if you don’t want to actually draw it custom. It might be sufficient to check for disallowed components in OnEnable.

2 Likes

DisallowMultipleComponent’s docs says that it also applies to child classes. So you could have an abstract superclass for your two classes that can’t be on the same object and mark that with DisallowMultipleComponents.

Didn’t know about that attribute at all.

Yes… But maybe, if there was a way to check how it is implemented in C++, then maybe there would be a way to reproduce it, e.g. maybe conflicting components is stored in some sort of array, and there is a way to expand it.

I can’t make built-in components to derive from my class.

That’s interesting hack, but the problem is that it will work only in the editor and only on selected object (for each component which has opened inspector).

Seems like “Update + GetComponentInChildren + constant buffer” solution will give some sort of required effect, but it does not implement real preventing of component adding. And also no stack trace is present after attempt of adding conflicted component. But for debug purposes might be more that enough (at least you will know what conflicts with what). Also I have posted an idea to create such attribute in suggestions. Alas, there is no way to fix suggestion text, hope someone will understand what is written there.