유니티의 상속클래스를 어셋으로 저장하는 방법을 기록한다.
1. 기본노드.
기본 노드는 스크립터블 오브젝트(ScriptableObject) 를 상속한다.
// Node.cs
using UnityEngine;
public abstract class Node : ScriptableObject
{
public int BaseData;
public virtual void Draw()
{
Debug.Log("Base Draw");
}
public virtual void OnInspector()
{
GUILayout.Label("Base Node");
}
// Hide 플래그를 지정하지 않으면 릭이 발생한다.
public void OnEnable() { hideFlags = HideFlags.HideAndDontSave; }
}
2. 상속받은 노드.
특별한건 없다.
// NodeA.cs
using UnityEngine;
public class NodeA : Node
{
public float AData;
public override void Draw()
{
Debug.Log("A Draw");
}
public override void OnInspector()
{
GUILayout.Label("A Node");
}
}
// NodeB.cs
using UnityEngine;
public class NodeB : Node
{
public string BData;
public override void Draw()
{
Debug.Log("B Draw");
}
public override void OnInspector()
{
GUILayout.Label("B Node");
}
}
3. 리스트.
노드들의 리스트를 가진 클래스. 이역시 ScriptableObject 를 상속받는다.
// NodeList.cs
using UnityEngine;
using System.Collections.Generic;
public class NodeList : ScriptableObject
{
public List<Node> nodes = new List<Node>();
// Hide 플래그를 지정하지 않으면 릭이 발생한다.
public void OnEnable() { hideFlags = HideFlags.HideAndDontSave; }
}
4. 저장.
노드가 ScriptableObject를 상속받았으므로, ScriptableObject.CreateInstance 를 이용해 인스턴스를 생성한다.
특이점은, 각각의 노드 또한 AssetDatabase.AddObjectToAsset 를 사용해 추가 저장해줘야한다는것.
노드 요소들에 hideFlag 를 정해주지 않으면, 빈 어셋에 여러개의 서브어셋이 들어간 모양새가 된다.
MainAsset을 제외하고는 hideFlags 를 HideFlags.HideInHierarchy 로 설정해준다.
NodeList list = ScriptableObject.CreateInstance<NodeList>();
list.hideFlags = HideFlags.None;
NodeB n = ScriptableObject.CreateInstance<NodeB>();
n.BaseData = 10;
n.BData = "Ho!!";
n.hideFlags = HideFlags.HideInHierarchy;
NodeA a = ScriptableObject.CreateInstance<NodeA>();
a.BaseData = 20;
a.AData = 2.1f;
a.hideFlags = HideFlags.HideInHierarchy;
NodeA b = ScriptableObject.CreateInstance<NodeA>();
b.BaseData = 30;
b.AData = 3.1f;
b.hideFlags = HideFlags.HideInHierarchy;
list.nodes.Add(n);
list.nodes.Add(a);
list.nodes.Add(b);
AssetDatabase.CreateAsset(list, path);
list.nodes.ForEach(node => { AssetDatabase.AddObjectToAsset(node, list); });
AssetDatabase.SaveAssets();
EditorUtility.FocusProjectWindow();
Selection.activeObject = list;
5. 로드
NodeList list = AssetDatabase.LoadAssetAtPath(path, typeof(NodeList)) as NodeList;
if (list == null)
Debug.Log("Error:)");
else
list.nodes.ForEach(node => { Debug.Log(node.BaseData); });
6. 주의 할것.
1) ScriptableObject 에 저장되는 유효값은 public 이거나, [SerializeField] 속성을 가져야 한다.
2) AssetDatabase.CreateAsset 에 저장되는 path는 '.asset' extension 을 가져야 한다. 그 외의 확장자명은 정상 처리되지 않는다.
3) hideFlags 를 평소에는 HideFlags.HideAndDontSave 로 설정해줘야지 에디터 창을 닫는다던가 할때 릭이 발생하지 않는다.
저장할때만 리스트는 HideFlags.None 노드는 HideFlags.HideInHierarchy 로 설정하여 저장한다(아니면 에러가 뜬다.)
이후 저장이 종료되면 다시 HideAndDontSave로 설정해줘야 하는데 OnEnable() 에서 설정해주면 알아서 된다.
참고 : http://forum.unity3d.com/threads/155352-Serialization-Best-Practices-Megapost
'Unity3D' 카테고리의 다른 글
[transform] Enable/Disable (0) | 2015.12.01 |
---|---|
[editor] Sprite Packer does not work... (0) | 2015.07.01 |
[NGUI] UI와 일반 오브젝트의 터치 이벤트 처리. (1) | 2013.09.02 |
실시간 컴포넌트 교체. (0) | 2013.08.19 |