5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Unity] Attributeいろいろ

5
Last updated at Posted at 2024-05-31

はじめに

Attributeとは、

[SerializeField,Range(0,1)] float rate=0f

のように、変数やクラスの前にある[]内の定義のことです。

Unityでよく使うor便利なAttributeをまとめてみました。

実際に試すのが一番わかりやすいので、下記のスクリプトを空のGameObjectにアタッチし、子の階層にCreate>3DObject>Cubeしてみてください
image.png

スクリプト
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が開きます。
image.png

[DisallowMultipleComponent]

GameObjectに同じコンポーネントを追加できないようにします
既にAttributeSamplesがアタッチされているGameObjectに対して再度AttributeSamplesをアタッチしようとすると
image.png
のように警告が表示されます。

[DefaultExecutionOrder(-10)]

Script Execution Orderをスクリプトから設定します
image.png

[SelectionBase]

Sceneで子Objectを選択した時もInspectorに表示されるようにします
image.png
Sceneで子ObjectのCubeを選択しましたが、InspectorにはAttributeSamplesが表示されています。

[ExecuteAlways]

プロパティやSceneが変更された時のみ、エディター非Play中もUpdate()が実行されます
以前は[ExecuteInEditMode]というAttributeがありましたが、こちらは将来廃止されるようです。

[System.Obsolete("message")]

Classの下に警告を出します。また、スクリプト名の後ろに(Deprecated)と表示されます
image.png

enumに追加するAttribute

[InspectorName("name")]

Inspectorで表示される名前を変更します

[InspectorName("2だけどOne")]
OneBut2 = 2,
[InspectorOrder()]

Inspectorで表示時に名前でソートします
image.png

[System.Flags]

enumをフラグとして使用できます。
NoneとEverythingは自動的に追加されます。
image.png

変数に追加するAttribute

[Tooltip("message")]

変数をマウスオーバーしたときにツールチップを表示します
image.png

[ContextMenuItem("message", "function")]

変数を右クリックしたときのメニューを追加します
image.png

[ColorUsage(bool, bool)]

ColorのAlpha,hdr変更を可能にします
image.png

[GradientUsage(bool)]

Gradientをhdrにします
image.png

[Delayed]

値を確定後に変更します
通常、Inspectorで変更した変数は即座に反映されますが、[Delayed]を付けた変数はリターンを押す、フォーカスを外すなど値を変更確定した後に更新されます。

[Range(min, max)]

Inspector上にスライダーを表示します
image.png

[Multiline(num)]

String変数の表示行数を変更します
image.png

[FormerlySerializedAs("previousName")]

Inspectorの値を保持したまま変数名を変更します
using UnityEngine.Serialization;の宣言が必要になります。
通常、例えばfloat fvalfloat rateValのように変更すると、fvalに設定されていた値は消えてしまいますが、

 [SerializeField, FormerlySerializedAs("fval")] float rateVal;

のように変更前の変数名を指定することで、rateValに値を引き継ぐことができます。
例えば変数fval10.fであった場合、変更後の変数rateVal10.fになります。
また、Unityではfvalm_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の幅比率を変更することができます

image.png

機能 表示
TwoColumns 左右に表示(default) image.png
OneColumnWithValueFoldout Keyの下にValueを折りたたんで表示 image.png
DictionaryLayout.OneColumnWithValueVisible Keyの下にValueを表示 image.png
[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;
        }
 :
 

のようにエディタ拡張を追加することで表示されるようになります
image.png

関数に追加するAttribute

[ContextMenu("message")]

スクリプトを右クリックしたときに表示されるリストに項目を追加し、選択時に実行します
image.png

using Unity.Cinemachine で使用できるようになるもの

[MinMaxRangeSlider(-10, 10)]

using Unity.Cinemachine; を加えることで、
image.png
最小値・最大値を設定できるようになります。
image.png

まとめ

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

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?