Unity/개발연습

[Unity] Behaviour Tree Editor 제작기 - 4

민트초밥 2024. 8. 30. 14:12

현재 Node들은 아래와 같이 상속 구조를 따르고 있다.

 

 

 

 

 

모든 Node들은 BehaviourTree 클래스에서 관리하고 직렬화를 하는데 직렬화 과정에서 다형성이 지원이 안 되는 것 같아서 아래와 같이 Data들만 따로 관리하는 클래스를 만들어서 해당 객체를 직렬화하는 방식으로 우회했었다.

// 다형성 문제 발생 
// ex) ActionNode가 Serialization/Deserialization 되면 BehaviourNode가 됨
public List<BehaviourNode> NodeList = new List<BehaviourNode>();

 

public List<BehaviourNode> NodeList = new List<BehaviourNode>();
public List<BehaviourNodeData> NodeDataList = new List<BehaviourNodeData>();

public void OnBeforeSerialize()
{
    NodeDataList.Clear();

    for (int i = 0; i < NodeList.Count; i++)
    {
		// BehaviourNode가 아닌 BehaviourNodeData를 직렬화
        BehaviourNodeData nodeData = new BehaviourNodeData();
        nodeData.TypeName = NodeList[i].GetType().Name;
        nodeData.Guid = NodeList[i].Guid;
        nodeData.ParentNodeGuid = NodeList[i].ParentNodeGuid;
        nodeData.ChildNodeGuidList = NodeList[i].ChildNodeGuidList;
        nodeData.PosX = NodeList[i].PosX;
        nodeData.PosY = NodeList[i].PosY;

        NodeDataList.Add(nodeData);
    }
}

public void OnAfterDeserialize()
{
    NodeList.Clear();

    for (int i = 0; i < NodeDataList.Count; i++)
    {
        Type type = Type.GetType(NodeDataList[i].TypeName);

        BehaviourNode node = Activator.CreateInstance(type, NodeDataList[i].Guid) as BehaviourNode;
        node.PosX = NodeDataList[i].PosX;
        node.PosY = NodeDataList[i].PosY;
        node.ParentNodeGuid = NodeDataList[i].ParentNodeGuid;
        node.ChildNodeGuidList = NodeDataList[i].ChildNodeGuidList;

        NodeList.Add(node);
    };    
}


[Serializable]
public class BehaviourNodeData
{
    public string TypeName;

    public string Guid;
    public string ParentNodeGuid;
    public List<string> ChildNodeGuidList;
    public float PosX;
    public float PosY;
}

 

BehaviourTree Scriptable Asset 파일 내부 데이터

 

 

 

 

기능 구현엔 큰 문제가 없었지만 개별 노드에 필드를 추가할 때 문제가 발생했다.

BehaviourNode를 직렬화 하는 것이 아니기 때문에 필드가 추가될 때마다 BehaviourNodeData에도 해당 필드를 같이 추가해 주어야 된다.

 

Node의 개수가 적으면 상관없지만 Node의 종류가 늘어날 때마다 추가해야 되는 번거로움이 있으며,

특히 해당 필드가 필요없는 Node들에도 값이 추가된다는 문제가 생겼다.

 

MoveSpeed가 모든 Node에 포함됨

 

 

 

 

결국 이 방법은 비효율적이라 판단 다른 방법을 찾아보니 다형성이라도 직렬화하는 방법이 있는 것 같다.

 

 

 

스크립트 직렬화 - Unity 매뉴얼

직렬화는 데이터 구조 또는 게임 오브젝트 상태를 Unity가 보관하고 나중에 다시 복구할 수 있는 포맷으로 변환하는 자동 프로세스입니다.

docs.unity3d.com

 

 

 

 

[SerializeReference] 어트리뷰트만 추가하면 될까?? 해서 일단 적용해 봤다.

[SerializeReference]
public List<BehaviourNode> NodeList = new List<BehaviourNode>();

 

 

 

 

문서에 "[SerializeReference]는 일부 오버헤드를 추가하지만 다음 경우를 지원합니다." 이런 말이 있어서 직렬화되는 데이터가 달라진 것 같지만(ex. rid, type...) 다형성의 직렬화는 정상적으로 된 것 같다.

 

MoveSpeed도 적용된 Node에만 추가된 것을 확인할 수 있다.

 

 

 

 


 

 

 

어떤 문제가 또 생길지 모르기 때문에 일단은 이렇게 진행해 볼 예정이다.

 

 

GitHub - mintchobab/Unity_Practice_Editor

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

github.com

 

 

반응형