- Home /
Custom attributes?
So I'd like to understand a bit about when to use attributes. I understand that they add metadata about objects. I have a node-based editor I'm making, and each node needs a name, description, and a position in the editor. This information is irrelevant in-game, so would I use an attribute to handle that data?
Answer by sysameca · Feb 08, 2015 at 10:32 PM
Attributes are powerful way to provide meta information which can be associated with methods properties fields and etc and can be retrieved in runtime. This meta information is usually accessed through reflection and from there you can do whatever you want with that "marked" field, method, object and so forth. I will give you a short example because i feel sleepy.
Say you want to mark some fields and give the position meta information so later on you can work with it. First let's create the attribute:
[AttributeUsage(AttributeTargets.Field)]
public class PositionAttribute : Attribute
{
public readonly Vector2 position;
public PositionAttribute(int x, int y)
{
position.x = x;
position.y = y;
}
}
Now let's mark some script fields with that attribute:
public class Node : MonoBehaviour
{
[Position(1, 0)]
public object node;
}
So now let's create a small custom inspector for the Node.
using UnityEngine;
using UnityEditor;
using System.Reflection;
using System;
[CustomEditor(typeof(Node))]
class NodeCustomEditor : Editor
{
private void OnEnable()
{
MonoBehaviour[] sceneActive = GameObject.FindObjectsOfType<MonoBehaviour>();
foreach (MonoBehaviour mono in sceneActive)
{
Type monoType = mono.GetType();
// Retreive the fields from the mono instance
FieldInfo[] objectFields = monoType.GetFields(BindingFlags.Instance | BindingFlags.Public);
// search all fields and find the attribute [Position]
for (int i = 0; i < objectFields.Length; i++)
{
PositionAttribute attribute = Attribute.GetCustomAttribute(objectFields[i], typeof(PositionAttribute)) as PositionAttribute;
// if we detect any attribute print out the data.
if (attribute != null)
{
Debug.Log(attribute.position.x); // The attribute position Y for that instance variable "1"
Debug.Log(attribute.position.y); // The attribute position X for that instance variable "0"
Debug.Log(mono.GetType()); // The type of the mono script "Node"
Debug.Log(objectFields[i].Name); // The name of the marked variable - "node"
}
}
}
}
}
As you see when you mark that field you get access to exclusive information which you can't get in languages that does not support reflection. From here it's up to you how you will use that data. I hope i brought some small light about the Attributes. These are extremely powerful feature and if you learn how to use them you have another tool in your box :)
Answer by Alanisaac · Feb 08, 2015 at 09:38 PM
Regardless of whether its relevant in-game what you're describing sounds like the data of a node rather than metadata.
A field or property could be used to store each node's name, description, and position.
An attribute could be used, for example, to say that the name should not exceed 100 characters, or that the position field can't have negative x and y.
Those restrictions are not the data of each node but information about that data, or as you mentioned, "metadata". Does that make sense? See also http://unity3d.com/learn/tutorials/modules/intermediate/scripting/attributes
Answer by Xepherys · Oct 01, 2021 at 01:53 PM
Hate to raise a dead post, but I came across this one a few weeks ago while working on something and ended up writing a brief blog post about how I was using custom attributes to make a custom inspector more user-friendly:
https://www.labyrintheer.com/2021/10/01/unity-custom-attributes-and-custom-editors/
Hope that might help someone.
Your answer
Follow this Question
Related Questions
Drawing Editor Inspector GUI based on selected/current prefab (CustomPropertyDrawer) 2 Answers
Custom Asset Icons? 2 Answers
How to write a custom attribute? 1 Answer
Custom Editor loosing data on play 1 Answer
Material Array Using Custom Editor 0 Answers