Unity/개발연습

[Unity] Behaviour Tree Editor 제작기 - 5

민트초밥 2024. 9. 1. 00:26

개별 노드마다 추가된 필드가 저장 되도록 만들었는데 Editor에서 해당 필드 값이 보여지지 않고 수정도 불가능하다.

 

 

 

 

 

예전에 커스텀 애트리뷰트를 만들어본 적 있는데 그 때처럼 애트리뷰트를 추가하고 해당 애트리뷰트가 추가된 필드나 프로퍼티를 Node에 보여주면 될 것 같았다.

 

[Unity] Inspector에서 함수 실행하기

예전에 Ordin Inspector 에셋을 사용했을 때 그 안에 있었던 기능인데 가끔 필요할 때가 있어서 만들어 봤다.  Odin Inspector and Serializer | 유틸리티 도구 | Unity Asset StoreUse the Odin Inspector and Serializer from

mintchobab.tistory.com

 

 

 

 

Field에 추가할 수 있는 애트리뷰트 생성

using System;

[AttributeUsage(AttributeTargets.Field)]
public class NodeFieldAttribute : Attribute
{
    public NodeFieldAttribute() { }
}

 

 

 

 

Property 애트리뷰트도 생성

using System;

[AttributeUsage(AttributeTargets.Property)]
public class NodePropertyAttribute : Attribute
{
    public NodePropertyAttribute() { }
}

 

 

 

 

새롭게 생성한 애트리뷰트 추가

[SerializeReference, NodeField]
public float MoveSpeed;

[SerializeReference]
private float moveTime;

[NodeProperty]
public float MoveTime
{
    get => moveTime;
    set => moveTime = value;
}

 

 

 

 

중간 과정이 없긴 하지만...

해당 Node가 가지고 있는 NodeFieldAttribute를 찾아서 타입에 맞는 BaseField를 상속받는 Field를 생성하는 코드

 

여기서 BaseField는 TextField, InteagerField, FloatField 등등을 상속한다.

(※ Reflection의 Field랑은 다름.. VisualElement의 Field)

private void AddFields()
{
    FieldInfo[] fields = Node.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

    foreach (FieldInfo field in fields)
    {
        Attribute nodeAttribute = Attribute.GetCustomAttribute(field, typeof(NodeFieldAttribute));

        if (nodeAttribute != null)
        {
            if (field.FieldType == typeof(float))
            {
                CreateFieldView<float, FloatField>(field, () => new FloatField(field.Name));
            } 
            else if (field.FieldType == typeof(int))
            {
                CreateFieldView<int, IntegerField>(field, () => new IntegerField(field.Name));
            }
            else if (field.FieldType == typeof(string))
            {
                CreateFieldView<string, TextField>(field, () => new TextField(field.Name));
            }
        }
    }


    void CreateFieldView<TValue, TField>(FieldInfo fieldInfo, Func<TField> createFunc) where TField : BaseField<TValue>
    {
        TField fieldView = createFunc.Invoke();
        fieldView.value = (TValue)fieldInfo.GetValue(Node);

        fieldView.RegisterValueChangedCallback(evt =>
        {
            fieldInfo.SetValue(Node, evt.newValue);
            EditorUtility.SetDirty(tree);
        });

        extensionContainer.Add(fieldView);
    }
}

 

 

 

 

이렇게 개별 Node마다 Field나 Property를 추가할 수 있게 되었다.

 

 

 

 

 

GitHub - mintchobab/Unity_Practice_Editor

Contribute to mintchobab/Unity_Practice_Editor development by creating an account on GitHub.

github.com

 

반응형