Support passing non-strings into Attributes

Issue #2 open
Ivan Wang created an issue

It seems that early on in the design process, you decided to support string parameters in the constructors of different Attributes. While everything is very consistent, I'm not a huge fan for a few reasons:

  1. Strings are brittle and liable to break-- rename a field or function and you'll have to go back and edit all the attributes referring to it. (I'm a purist and type safety/compile-time checks are important to me! :P)

  2. There's no easy way to share properties between attributes in different files. Instead, you have to duplicate the same private variable or function to get the same functionality.

Take the following example:

Say I have a list of enemy names, defined in a static variable Enemy.Names. In various other files, I'd like to use the [ValueDropdown] attribute. Unfortunately, because it takes a string as argument, I can't refer to the static variable Enemy.Names, but have to create a private variable or getter that references it for every file.

Alternatively, in a potential v2 of the API, we could create the additional constructors:

ValueDropdown(IList<T> dropdown)
ValueDropdown(Func<IList<T>> dropdownFunc)

which behave identically to the current constructor, except they skip the Reflection step of finding the private method or variable.

Now I can do things like [ValueDropdown(Enemy.Names)]-- problem solved!

This could extend to more than just ValueDropdown: VisibleIf, ValidateInput, OnInspectorGUI, etc. could all benefit from this.

Comments (3)

  1. Bjarke Elias

    I absolutely agree with you, referring to a member with a loosely typed string is not ideal!! And a part of me dies every time I do it.

    Unfortunately the compiler doesn't give us any alternatives. Attributes are a compile-time thing and are stored as metadata in the assembly. So you can't pass any references to the constructor (with exceptions). Attributes only accept a few types: https://msdn.microsoft.com/en-us/library/aa664615(v=vs.71).aspx.

    One way of solving the issue would be to compile your code outside of unity in order to get the newer c# features, you can then take advantage of the nameOf keyword introduced in c# 6.0 which would allow you to make a strongly-typed association to Enemy.Values by writing:

    [ValueDropdown(nameOf(Enemy.Names))]
    

    However, right now you cannot refer to members outside of the class you are working in, but that is definitely something we want to do.

  2. Tor Esa Vestergaard
    • changed status to open

    Will add support for referring to members of other types for attribute member name parameters.

  3. Log in to comment