0
\$\begingroup\$

Unity's RequireComponent inherits from System.Attribute. Somehow they made it that whenever component is added it has a reference to GameObject its being added to. So they can callAddComponent` to it.

I am trying to replicate that behaviour.

My theory is that because UnityEngine.RequireComponent has types stored inside class - they do it by reflection later. In method AddComponent<T> they get T class attributes from type and then try to cast them, get information from them, and apply to GameObject. If that is the case, then I doubt I will be able to do something with it, unless I have access to change AddComponent<T> somehow.

Is there another way around it?(that is no problem to do in code (just extension), but what about how it will work in inspector) Maybe apply different method to Unity`s default component addition.

EDIT

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class RequireComponentAttribute : Attribute
{
    public RequireComponentAttribute(Type type, int quantity)
    {
        if (quantity < 0)
            throw new ArgumentOutOfRangeException("Required components quantity cannot be negative");
    }

#if UNITY_EDITOR
#endif
}
\$\endgroup\$
4
  • \$\begingroup\$ It's not clear where you want to obtain the reference to the game object? It looks pretty trivial to do within any of the MonoBehavior methods. Where are you trying to do it? Are you trying to determine this relationship from your own attribute (you probably cannot do that effectively)? Can you post an example of the code you're trying to make work? \$\endgroup\$
    – user1430
    Aug 23 '18 at 18:32
  • 2
    \$\begingroup\$ Since you are asking about how unity does it I will point that the source code has been released on github: github.com/Unity-Technologies/UnityCsReference \$\endgroup\$ Aug 23 '18 at 18:33
  • \$\begingroup\$ @TurtleKwitty thanks, that is very useful. The implementation is probably hidden and I wouldn't be able to change the behaviour anyway, so I think I will just leave it. \$\endgroup\$ Aug 24 '18 at 9:48
  • \$\begingroup\$ @Josh I have added a bit of code to make it clearer. In the best case I want to access the gameobject in constructor. But it doesn't seem possible. As it's an attribute and it actually has nothing to do with GameObject or instance itself. The way to do it is by reflection I suppose. But anyway, for it to work in editor as expected, I would need to modify the internal code which doesn't work. The only way is probably to ask Unity to reveal API for it or make changes to RequireComponent(that feature was requested a long time ago, but it doesn't seem important - it really isn't, just useful). \$\endgroup\$ Aug 24 '18 at 9:52
1
\$\begingroup\$

C# attributes do not work the way you'd need them to work to do what you want, here.

  • The constructor for your attributes don't run until the attribute is recovered through the reflection API (e.g., by calling Type.GetCustomAttributes()).

  • There's no API or other mechanism for the code in the attribute to "see outside" to what the attribute instance is attached to.

The behavior you're seeing from Unity is likely handled by reflection or something similar: when creating an instance of some type, the type is inspected (via GetCustomAttributes) for RequiredComponent attributes and instances of the types specified by any such attributes found are created and attached to the object.

If you create a wrapper around the creation of objects that you use everywhere, you can implement similar behavior via reflection. But you can't do it from the members of the attribute subclass code itself.

\$\endgroup\$

You must log in to answer this question.

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