はじめに
Attributeとは、
[SerializeField,Range(0,1)] float rate=0f
のように、変数やクラスの前にある[]内の定義のことです。
Unityでよく使うor便利なAttributeをまとめてみました。
実際に試すのが一番わかりやすいので、下記のスクリプトを空のGameObjectにアタッチし、子の階層にCreate>3DObject>Cubeしてみてください

スクリプト
using System.Collections.Generic;
using UnityEngine;
using Unity.Scripting.LifecycleManagement;
using Unity.Cinemachine; // [MinMaxRangeSlider()]
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Elix.Test {
#if UNITY_EDITOR
[CustomEditor(typeof(AttributeSamples))]
public class AttributeSamplesEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
var value = EditorGUILayout.IntField(
"My Static Value",
AttributeSamples.MyStaticValue);
AttributeSamples.MyStaticValue = value;
}
}
#endif
//Classにヘルプを追加します
[HelpURL("https://docs.unity3d.com/2022.3/Documentation/ScriptReference/HelpURLAttribute.html")]
//GameObjectに同じClassを追加できないようにします
[DisallowMultipleComponent]
//Sceneで子Objectを選択したときにInspectorに表示されるようにします
[SelectionBase]
//Script Execution Orderをスクリプトから設定します
[DefaultExecutionOrder(-10)]
//[ExecuteInEditMode]は将来廃止される予定
//[ExecuteAlways]
//Classの下に警告を出します(廃止された時などに使用)
[System.Obsolete("このクラスは廃止されます")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2200:Rethrow to preserve stack details", Justification = "Not production code.")]
public partial class AttributeSamples : MonoBehaviour
{
public enum OptionType{ Random, Loop, SpatialBlend, Priority, Spread, }
//enum表示時に名前でソートします
[InspectorOrder()]
public enum MyEnum
{
Auto = 0,
[InspectorName("2だけどOne")]
OneBut2 = 2,
[InspectorName("4だけどTwo")]
TwoBut4 = 4,
[InspectorName("1だけどThree")]
ThreeBut1 = 1,
}
[Tooltip("変数:右クリックメニューにアイテムを追加します")]
[ContextMenuItem("黄色に変更", "changeColorToYellow")]
//変数:ColorのAlpha,hdr変更を可能にします
[ColorUsage(false, true)]
// private変数をInspectorに表示します
[SerializeField]
Color _myCol = Color.red;
[Tooltip("変数:Gradientをhdrにします")]
[GradientUsage(true)]
public Gradient hdrGradient;
[SerializeField, Tooltip("実行時変数:値を確定後に変更します")]
[Delayed]
//Inspectorに変数のタイトルを表示します
[Header("transform.x")]
float _myPosX = 0f;
[SerializeField, Tooltip("変数:最小値と最大値を設定します")]
[Range(0, 2)] float _myRate = 0f;
[Tooltip("enum:enumに名前を付けます")]
public MyEnum myEnum = MyEnum.Auto;
[Tooltip("変数:stringの表示行数を変更します")]
[Multiline(3)]
public string m_myPoem = "朝焼夕焼食べるものがない\n種田山頭火";
[Header("using Unity.Cinemachine で使用できるようになるもの")]
[MinMaxRangeSlider(-10, 10)] public Vector2 m_myMinMax = Vector2.zero;
//enumをビットフラグとして使用できます
[System.Flags]
public enum AxisFlag{ None=0, X=1<<0, Y=1<<1, Z=1<<2, }
[SerializeField, Tooltip("enumをビットフラグとして使用できます")]
AxisFlag _rotAxis = AxisFlag.X | AxisFlag.Y;
[AutoStaticsCleanup] static int s_myStaticValue = 0;
public static int MyStaticValue
{
get => s_myStaticValue;
set => s_myStaticValue = value;
}
[SerializeField]
[DictionaryDisplay(keyLabel="target", valueLabel="value", keyColumnFraction=0.7f)]
Dictionary<string, int> myDictionary = new Dictionary<string, int>()
{
{ "Enemy0", 10 },
{ "Enemy1", 500 },
};
#pragma warning disable CS0414 // CS0414のワーニングを抑制
float noUsedValue = 0f;
#pragma warning restore CS0414 // CS0414のワーニング抑制を元に戻す
[Tooltip("スクリプト:ScriptのInspectorにメニューを追加します")]
[ContextMenu("緑に変更しxをゼロに")]
void changeColAndX()
{
changeColor(Color.green);
_myPosX = 0;
}
void changeColorToYellow() { changeColor(Color.yellow); }
void changeColor(Color _col)
{
_myCol = _col;
GradientColorKey[] colKeys = hdrGradient.colorKeys;
colKeys[0].color = _col;
hdrGradient.SetKeys(colKeys, hdrGradient.alphaKeys);
}
// Start is called before the first frame update
void Start()
{
Debug.Log(m_myPoem);
GradientColorKey[] colKeys = new GradientColorKey[2];
colKeys[0].color = Color.red;
colKeys[0].time = 0.0f;
colKeys[1].color = Color.blue;
colKeys[1].time = 1.0f;
hdrGradient.SetKeys(colKeys, hdrGradient.alphaKeys);
s_myStaticValue++;
Debug.Log("Static Value: " + s_myStaticValue);
}
// Update is called once per frame
void Update()
{
transform.position = new Vector3(_myPosX, 0, 0);
if (transform.childCount > 0)
{
_myRate= (_myRate+Time.deltaTime) % 2f;
Color col = hdrGradient.Evaluate(Mathf.PingPong(_myRate,1f));
transform.GetChild(0).GetComponent<Renderer>().sharedMaterial.SetColor("_Color", col);
if(_rotAxis != AxisFlag.None)
{
Vector3 axis = Vector3.zero;
if ((_rotAxis & AxisFlag.X) == AxisFlag.X) axis.x = 1f;
if ((_rotAxis & AxisFlag.Y) == AxisFlag.Y) axis.y = 1f;
if ((_rotAxis & AxisFlag.Z) == AxisFlag.Z) axis.z = 1f;
transform.GetChild(0).transform.rotation = Quaternion.AngleAxis(_myRate*360f,axis);
}
}
#if UNITY_EDITOR
// EditorでPlay中はログを出力しません
if (!EditorApplication.isPlaying)
{
Debug.Log("X:" + _myPosX.ToString());
}
#endif
}
}
}
以下は簡単な説明です。
Classに追加するAttribute
[HelpURL("url")]
Classにヘルプを追加します
スクリプトの後ろの?マークをクリックするとurlが開きます。

[DisallowMultipleComponent]
GameObjectに同じコンポーネントを追加できないようにします
既にAttributeSamplesがアタッチされているGameObjectに対して再度AttributeSamplesをアタッチしようとすると

のように警告が表示されます。
[DefaultExecutionOrder(-10)]
Script Execution Orderをスクリプトから設定します

[SelectionBase]
Sceneで子Objectを選択した時もInspectorに表示されるようにします

Sceneで子ObjectのCubeを選択しましたが、InspectorにはAttributeSamplesが表示されています。
[ExecuteAlways]
プロパティやSceneが変更された時のみ、エディター非Play中もUpdate()が実行されます
以前は[ExecuteInEditMode]というAttributeがありましたが、こちらは将来廃止されるようです。
[System.Obsolete("message")]
Classの下に警告を出します。また、スクリプト名の後ろに(Deprecated)と表示されます

enumに追加するAttribute
[InspectorName("name")]
Inspectorで表示される名前を変更します
[InspectorName("2だけどOne")]
OneBut2 = 2,
[InspectorOrder()]
[System.Flags]
enumをフラグとして使用できます。
NoneとEverythingは自動的に追加されます。

変数に追加するAttribute
[Tooltip("message")]
[ContextMenuItem("message", "function")]
[ColorUsage(bool, bool)]
[GradientUsage(bool)]
[Delayed]
値を確定後に変更します
通常、Inspectorで変更した変数は即座に反映されますが、[Delayed]を付けた変数はリターンを押す、フォーカスを外すなど値を変更確定した後に更新されます。
[Range(min, max)]
[Multiline(num)]
[FormerlySerializedAs("previousName")]
Inspectorの値を保持したまま変数名を変更します
using UnityEngine.Serialization;の宣言が必要になります。
通常、例えばfloat fvalをfloat rateValのように変更すると、fvalに設定されていた値は消えてしまいますが、
[SerializeField, FormerlySerializedAs("fval")] float rateVal;
のように変更前の変数名を指定することで、rateValに値を引き継ぐことができます。
例えば変数fvalが10.fであった場合、変更後の変数rateValも10.fになります。
また、Unityではfvalとm_fValはInspector上で同じfvalと表示されますが、
FormerlySerializedAsを指定しないとfvalに設定されていた値は消えてしまいます。
#pragma warning disable (not Attribute)
使用していない変数を定義すると
AttributeSamples.cs(77,15): warning CS0414: The field 'AttributeSamples.noUsedValue' is assigned but its value is never used
のようにワーニングが出ますが、
#pragma warning disable [ワーニング番号]```
float noUsedValue = 0f; //ワーニング番号が出る行
#pragma warning disable [ワーニング番号]```
のようにすることでワーニングを抑制できます。
Attributeではありませんが、一応記載しておきます。
[DictionaryDisplay]
Unity6.6から、Dictionary<>をInspectorに表示することができるようになりました。
その際、Keyとvalueのタイトルを指定することができます。
また、keyColumnFractionを指定することでkeyとvalueの幅比率を変更することができます
| 値 | 機能 | 表示 |
|---|---|---|
| TwoColumns | 左右に表示(default) | ![]() |
| OneColumnWithValueFoldout | Keyの下にValueを折りたたんで表示 | ![]() |
| DictionaryLayout.OneColumnWithValueVisible | Keyの下にValueを表示 | ![]() |
[AutoStaticsCleanup]
ProjectSettings > Editor EnterPlayModeSettings > When entering PlayMode
を Reload Scene Only にしていると(Unity6.6以降ではデフォルト)、実行時にstatic変数が初期化されなくなります。
AutoStaticsCleanup を使用することで実行時にstatic変数も初期化されるようになります。
このAttributeを使用するには
using Unity.Scripting.LifecycleManagement;
を宣言しておく必要があります。
ちなみに、static変数は Inspector に表示されませんが、
:
#if UNITY_EDITOR
using UnityEditor;
#endif
:
#if UNITY_EDITOR
[CustomEditor(typeof(AttributeSamples))]
public class AttributeSamplesEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
var value = EditorGUILayout.IntField(
"My Static Value",
AttributeSamples.MyStaticValue);
AttributeSamples.MyStaticValue = value;
}
}
#endif
:
[AutoStaticsCleanup] static int s_myStaticValue = 0;
public static int MyStaticValue
{
get => s_myStaticValue;
set => s_myStaticValue = value;
}
:
のようにエディタ拡張を追加することで表示されるようになります

関数に追加するAttribute
[ContextMenu("message")]
スクリプトを右クリックしたときに表示されるリストに項目を追加し、選択時に実行します

using Unity.Cinemachine で使用できるようになるもの
[MinMaxRangeSlider(-10, 10)]
using Unity.Cinemachine; を加えることで、

最小値・最大値を設定できるようになります。

まとめ
Unity2022あたりから、地味に地味に使いやすくなってきたEditorですが、その恩恵を受けてAttributeもいろいろ追加されているようです。
さらに詳しく知りたい方は
こちらからはじまるAttributesを確認してください。

Attributes全体へのURLってないんですよね。。。









