본문 바로가기
개발/Unity 내일배움캠프 TIL

Unity 어트리뷰트 (Attribute)

by 석시 2023. 9. 22.



유니티에서는 에디터를 쉽게 커스텀할 수 있도록 여러 가지 기능들을 제공해주고 있다.

그 중 하나가 이 어트리뷰트(Attribute)이다.

오늘은 다양한 어트리뷰트들과 그 기능에 대해 알아보자.

직렬화 관련

SerializeField

데이터를 직렬화하여 한정자가 private인 변수임에도 Inspector에서 볼 수 있게 해주는 기능이다.

public class CharacterStats : MonoBehaviour
{
    [SerializeField]
    private int _level;
}

private 변수임에도 Inspector에 나타난다. 수정도 가능하다!

HideInInspector

반대로 HideInInspectorpublic인 변수를 Inspector에 노출시키고 싶지 않을 때 사용한다.

비슷한 기능으로 System.Nonserialized가 있는데,

HideInInspector는 인스펙터에서 숨기기 전에 값을 변경했을 경우 그 변경 값이 남아있는데, System.Nonserialized는 해당 변경 값이 반영되지 않는다.

Serializable

내가 직접 구현한 클래스는 public으로 열어줘도 Inspector에서 클래스의 각 필드를 수정할 수가 없다.

그것을 Inspector에서 가능하도록 열어주는 어트리뷰트가 Serializable이다.

public enum StatsChangeType
{
    Add,
    Multiple,
    Override,
}

[Serializable]
public class CharacterStats
{
    public StatsChangeType statsChangeType;
}

public class CharacterStatsHandler : MonoBehaviour
{
    [SerializeField] private CharacterStats baseStats;
}


인스펙터 커스텀 관련

Header

인스펙터에 뜨는 변수들을 구간을 나눠 제목을 달아주는 어트리뷰트이다.

public class SO_ItemBasicInfo : ScriptableObject
{
    [Header("Item Info")]
    [SerializeField]
    private Sprite _uiSprite;
    public Sprite UiSprite {  get { return _uiSprite; } }
    [SerializeField]
    private ItemType _itemType;
    public ItemType ItemType { get { return _itemType; } }
    [SerializeField]
    private string _itemName;
    public string ItemName { get { return _itemName; } }
    [SerializeField]
    private string _itemDescription;
    public string ItemDescription { get { return _itemDescription; } }

    [Header("Item Stat")]
    [SerializeField]
    private int _attack;
    public int Attack { get { return _attack; } }
    [SerializeField]
    private int _defense;
    public int Defense { get { return _defense; } }
    [SerializeField]
    private int _maxHp;
    public int MaxHp { get { return _maxHp; } }
    [SerializeField]
    private float _critChance;
    public float CritChance { get { return _critChance; } }
}

Space

인스펙터에서 두 변수 사이를 띄워준다.

아무 값도 넣지 않으면 반 칸정도? 띄워진다.

[Header("Item Stat")]
[SerializeField]
private int _attack;
public int Attack { get { return _attack; } }
[SerializeField, Space]
private int _defense;
public int Defense { get { return _defense; } }
[SerializeField, Space(100)]
private int _maxHp;
public int MaxHp { get { return _maxHp; } }
[SerializeField]
private float _critChance;
public float CritChance { get { return _critChance; } }

Tooltip

매개변수로 넣은 string을 마우스를 가까이 가져다 댔을 때 설명으로 띄워준다.

[Header("Item Stat")]
[SerializeField, Tooltip("공격력")]
private int _attack;
public int Attack { get { return _attack; } }
[SerializeField , Tooltip("방어력")]
private int _defense;
public int Defense { get { return _defense; } }
[SerializeField, Tooltip("최대체력")]
private int _maxHp;
public int MaxHp { get { return _maxHp; } }
[SerializeField, Tooltip("크리티컬확률")]
private float _critChance;
public float CritChance { get { return _critChance; } }

Range

int, float과 같은 숫자형 변수의 경우 그 범위를 제한해준다.

[Serializable]
public class CharacterStats
{
    public StatsChangeType statsChangeType;
    [Range(1, 100)] public int maxHealth;
    [Range(1, 20f)] public float speed;
}

Multiline

기본적으로 인스펙터에 string을 띄우면 Text를 입력하는 구간이 한 줄이다.

Multiline은 string 변수를 여러 줄을 입력할 수 있도록 해주는 어트리뷰트이다.

자매품으로 TextArea가 있는데, 인스펙터 상에서 약간 다르게 기능한다. 이는 폭에 맞추어 자동으로 줄바꿈을 해주고, 스크롤바가 있다.

public class CharacterStats
{
    public string SinglelineText;
    [Multiline(5)]
    public string MultilineText;
    [TextArea]
    public string TextAreaText;
}

RequireComponent

해당 스크립트를 추가할 때 필수적으로 요구되는 컴포넌트를 달아줄 수 있다.

[RequireComponent(typeof(BoxCollider2D))]
public class CharacterStats : MonoBehaviour
{
}
CharacterStats만 추가했는데도 Box Collider가 같이 달린다.


에디터 커스텀 관련

CreateAssetMenu

ScriptableObject를 Create 메뉴를 통해 생성할 수 있도록 해준다.

[CreateAssetMenu(fileName = "CharacterBasicStat", menuName = "Scriptable Object/CharacterBasicStat", order = int.MinValue)]
public class SO_CharacterBasicStat : ScriptableObject
{

}

[CreateAssetMenu(fileName = "ItemBasicInfo", menuName = "Scriptable Object/ItemBasicInfo", order = int.MinValue + 1)]
public class SO_ItemBasicInfo : ScriptableObject
{

}

MenuItem

메뉴바에 기능을 추가하는 어트리뷰트이다.

public class PlayerPrefsEditorUtility : MonoBehaviour
{
    [MenuItem("PlayerPrefs/Delete All")]
    static void DeletePlayerPrefs()
    {
        PlayerPrefs.DeleteAll();
        Debug.Log("All PlayerPrefs deleted");
    }

    [MenuItem("PlayerPrefs/Save All")]
    static void SavePlayerPrefs()
    {
        PlayerPrefs.Save();
        Debug.Log("PlayerPrefs saved");
    }
}

ContextMenu

컴포넌트 제어 메뉴창에 원하는 함수를 추가시켜주는 기능이다.

[ContextMenu("Hello?")]
private void DebugPrint()
{
    Debug.Log("Hello?");
}

AddComponentMenu

AddComponent 메뉴창에 내가 만든 스크립트를 추가시켜주는 기능이다.

[AddComponentMenu("Characters/Character")]
public class Character : MonoBehaviour
{

}

ExecuteInEditMode

이 어트리뷰트를 붙인 스크립트는 에디터에서 플레이모드에 들어가지 않아도 동작한다!

Awake와 Start는 에디터 상에서 오브젝트에 컴포넌트가 부착될 때, Update는 컴포넌트가 부착된 오브젝트에 변화가 생길 때마다 호출된다.


Uploaded by N2T