0
\$\begingroup\$

Can I reset the [DisallowMultipleComponent] attribute in child classes in Unity somehow?

I want to create my base class:

[DisallowMultipleComponent]
public class MyCompanyClass : Monobehaviour {}

I want all my component scripts to inherit from the MyCompanyClass. So, I will be able to add only one instance of my component script to a game object at a time. I need it for most of my classes. But for some classes I still want to preserve the ability to add a few class instances to a game object, while still inheriting from the MyCompanyClass (because I am going to put some custom behavior into it, which is going to be used by all my component scripts).

So, I was trying to search for something like [AllowMultipleComponent], but found nothing. Is there maybe another way to achieve what I want?

\$\endgroup\$
1
  • \$\begingroup\$ If you can tell us a bit about this custom behaviour you're using this to implement, we may be able to recommend more flexible ways to achieve it that won't run into this particular problem. \$\endgroup\$
    – DMGregory
    Commented Apr 17, 2021 at 12:31

1 Answer 1

2
\$\begingroup\$

I can think of a couple of ways to achieve that. You can either: Write some boilerplate code to check whether a Component is present multiple times or not at runtime (boring and error-prone). Or, you can play around with inheritance and interfaces (which is Vaillancourt's good proposed solution, plus an extra by me).

The latter method grants in-editor and debugging feedback. You can also extend one of the methods above to include additional in-editor support, such as warning messages and stuff, but that's up to you (I'm not into UnityEditor scripting that much).

Combine [DisallowMultipleComponent] and inheritance

This method requires you to have a base class (MyCompanyClass) with all properties and functions you need. Then, another class (MyCompanyClassOneInstance) extends the base class, therefore inheriting all non-private properties and functions. Besides, it has the class attribute [DisallowMultipleComponent] that applies to all subclasses as well. Here's a (very bad) schema of inheritance and sample class code:

UML Schema

MyCompanyClass.cs:

using UnityEngine;

public class MyCompanyClass : MonoBehaviour { ... }

MyCompanyClassOneInstance.cs:

using UnityEngine;

[DisallowMultipleComponent]
public class MyCompanyClassOneInstance : MyCompanyClass { ... }

Every script that extends MyCompanyClass will behave as a regular MonoBehaviour; those that extend MyCompanyClassOneInstance will do the same but cannot be more than one per GameObject. If you need private properties to be available to subclasses, use the protected modifier instead.

Extending with interfaces

Another problem that may arise is different classes are considered different types. You can solve it with interfaces: if MyCompanyClass implements the interface IMyCompany, it is considered an object of either type (with some code tweaks). Then:

UML Schema 2

IMyCompany.cs:

interface IMyCompany
{
    void Fun1();
    void Fun2();
    ...
}

MyCompanyClass.cs:

using UnityEngine;

public class MyCompanyClass: MonoBehaviour, IMyCompany
{
    public void Fun1() { ... }
    public void Fun2() { ... }
}

MyCompanyClassOneInstance.cs:

using UnityEngine;

[DisallowMultipleComponent]
public class MyCompanyClassOneInstance : MyCompanyClass
{
    // Fun1() and Fun2() already implemented in MyCompanyClass
}

This way you can operate on MyCompanyClass and MyCompanyClassOneInstance components regardless of their actual type and just reference them by their interface type:

IMyCompany component1 = FindObjectOfType<MyCompanyClass>();
IMyCompany component2 = FindObjectOfType<MyCompanyClassOneInstance>();
component1.Fun1();
component2.Fun2();
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .