본문 바로가기
C#/Unity

Unity에서 속성(Attribute) 사용법과 커스텀 속성 만들기

by GangDev 2024. 4. 19.

 

Unity에서 속성(Attribute)은 스크립트에서 클래스, 프로퍼티 또는 함수 위에 명시하여 특별한 동작을 나타낼 수 있는 표식이다.

이를 통해 인스펙터(Inspector)에서의 표시 방식을 조정하거나, 직렬화 시스템을 제어하는 등의 기능을 수행할 수 있따.

 

속성의 사용 예시 >>

* HideInInspector: 프로퍼티가 공용 프로퍼티인 경우에도 인스펙터에 표시되지 않도록 한다. 이는 특정 값을 숨기고 싶을 때 사용된다.

[HideInInspector]
public float strength;

 

* SerializeField: 클래스 멤버 변수의 데이터를 직렬화하여 인스턴스가 생성되었을 때 Unity 시스템에서 직렬화한 데이터로 초기화 시켜주는 속성이다. 이는 접근 제한자(public, protected, private)에 상관없이 사용할 수 있다.

 

[SerializeField]
public int limitCount;

 

* NonSerialized: 해당 멤버 변수의 직렬화를 아예 막는 속성이다. 이는 특정 값을 직렬화 시스템에서 제외하고 싶을 때 사용된다.

[System.NonSerialized]
public int gameCount;

 

* AddComponentMenu: 이 속성을 사용하면 Unity에서 커스텀 컴포넌트를 추가할 수 있다. 인스펙터 창의 "COmponent Menu" 또는 "Add Component"에서 새로운 컴포넌트로 표시된다.

[AddComponentMenu("My Menu/New Component")]
public class AttributesDemoScript : MonoBehaviour
{
}

 

* Header: 인스펙터에서 필드 위에 헤더를 추가하는 데 유용하다. 이를 통해 인스펙터 내에서 관련 필드를 더욱 명확하게 구분할 수 있다.

[Header("Sphere variable")]
public GameObject ball;

 

커스텀 속성 생성 >>

Unity에서 직접 속성을 만들어 사용할 수 있다.

이를 통해 인스펙터 창에서의 표시 방식을 더욱 세밀하게 조정할 수 있다.

예를 들어, 열거형(Enum) 변수에 대한 커스텀 속성을 만들어 사용할 수 있다.

using System;
using UnityEngine;

public class EnumFlagAttribute : PropertyAttribute
{
    public Type enumType;

    public EnumFlagAttribute() { }
}

 

위 코드는 PropertyAttriubte를 상속받아 새로운 속성을 정의한 예시다.

이렇게 생성된 속성은 PropertyDrawer와 함께 사용하여 인스펙터 창에서의 표시 방식을 변경할 수 있다.

[CustomPropertyDrawer(typeof(EnumFlagAttribute))]
public class SomeEnumFlagDrawer : PropertyDrawer { ... }

 

 

Unity의 속성은 스크립트의 다양한 부분을 더욱 유연하게 제어할 수 있게 해주며, 개발자가 직접 속성을 정의하여 인스펙터의 기능을 확장할 수 있게 한다.

이는 특히 대규모 프로젝트에서 유용하게 사용될 수 있다.

 

SerializeField와 직렬화

SerializeField는 Unity에서 스크립트 내의 변수를 직렬화하도록 강제하는 속성이다.

일반적으로, 직렬화는 데이터를 재구성할 수 있는 형태로 포맷팅하는 과정을 의미한다.

Unity에서는 이를 통해 인스펙터(Inspector)에서 변수를 표시할 수 있게 된다.

기본적으로 Unity는 공용 필드만 직렬화하므로, 대부분의 공용 변수가 인스펙터에 표시된다.

그러나 비공개 필드는 직렬화되지 않으므로 표시되지 않는다.

SerializeField 속성은 비공개 필드를 직렬화하도록 강제하며, 이는 다른 스킓트에서 접근할 수 없지만, 인스펙터에서는 공용 필드처럼 표시된다.

 

직렬화는 객체의 상태 정보를 저장하거나 전송할 수 있는 형태로 변환하는 과정이다.

직렬화 과정에서 객체는 현재 상태를 임시 또는 영구 저장소에 기록한다.

나중에 객체는 저장소에서 객체의 상태를 읽어 다시 만들 수 있다.

이는 프로그램이 실행되는 동안 생성되고, 도달할 수 없을 때 회수되는 객체에 대해 적용된다.

객체의 내용을 영구적으로 저장하고 싶을 때 직렬화가 필요하다.

예를 들어, 객체의 상태를 바이트 시퀀스로 변환하고 저장 매체에 저장한 후, 필요할 때 다시 읽어 객체를 재구성할 수 있다.

 

Unity에서는 [SerializeField] 속성을 사용하여 비공개 또는 보호된 속성을 직렬화할 수 있다.

이는 Unity의 내부 직렬화 기능이다.

따라서 인스펙터에서 필드를 편집할 때 직렬화된 데이터를 편집하게 된다.

컴파일 시에 데이터는 다시 역직렬화되어 필드에 할당된다.

 

Unity의 직렬화 규칙에 따르면, 필드는 공용이거나 SerializeField 속성을 가지고 있어야 한다.

또한, 정적이지 않고 상수도 아니며, 읽기 전용도 아니어야 한다.

직렬화 가능한 필드 유형에는 기본 데이터 유형(int, float, double, bool, string 등), 열거형(32비트 이하), 고정 크기 버퍼, Unity 내장 유형(예: Vector2, Vector3, Rect, Matrix4x4, Color, AnimationCurve), 직렬화 가능한 사용자 정의 구조체 및 클래스, UnityEngine.Object에서 파생된 객체애 대한 참조, 그리고 위에서 언급한 유형의 배열 또는 리스트가 포함된다.

 

따라서, SerializeField 는 Unity 프로젝트에서 비공개 필드를 인스펙터에서 편집 가능하게 만들고, 이를 직렬화하여 게임 오브젝트의 상태를 저장하고 불러올 수 있게 하는 데 중요한 역할을 한다.