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:
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.
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:
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();