[졸업 작품, Unity]Item EditorWindow로 관리하기

2025. 3. 18. 00:39·Editor

오늘은 전에 만들었던 Item들을 관리하고 생성해주는 EditorWindow를 만들어봤다.

 

EditorWindow는 UIToolkit과 같이 사용할 수 있어서 같이 사용하였다.

 

어케함?

먼저 cs와 uss uxml이다.

using System;
using System.Collections.Generic;
using System.Linq;
using LJS.Item;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.Rendering.UI;
using UnityEngine.UIElements;

public class ItemCreater : EditorWindow
{
    [SerializeField]
    private VisualTreeAsset m_VisualTreeAsset = default;
    [SerializeField]
    private StyleSheet _styleSheet;
    [SerializeField]
    private ItemDataTableSO _itemDataTable;
    
    public static Action<string> _ShowItemEvent;
    
    private readonly string _itemVisual = "item-visual";
    private readonly string _itemLabel = "item-label";
    private readonly string _itemVisualSelect = "item-visual-select";
    private readonly string _itemFilePath = "Assets/00Work/LJS/05_SO/Item";
    
    private static float width = 900;
    private static float height = 700;

    #region Toolkit Elements

    private VisualElement _root;
    private VisualElement _itemView;
    private Label selectedLabel;
    private TextField fileNameField;
    private EnumFlagsField _typeOfItem;
    private TextField _descriptionField;
    private ObjectField _spriteField;
    private Toggle _endImmediatelyToggle;
    private IntegerField _EffectEndTime;
    private IntegerField _healCountField;
    private IntegerField _damageCountField;
    private IntegerField _defenceDecreaseField;
    private IntegerField _defenceIncreaseField;
    private IntegerField _strengthField;
    private IntegerField _weaknessField;
    private VisualElement _valueList;

    #endregion
    
    [HideInInspector] public VisualElement _selected;
    protected Dictionary<string, Label> _viewLabelDictionary;

    private Editor _cachedEditor;
    
    public void CreateGUI()
    {
        _root = rootVisualElement;
        
        rootVisualElement.style.flexGrow = 1f;
        
        VisualElement labelFromUXML = m_VisualTreeAsset.Instantiate();
        _root.Add(labelFromUXML);

        #region Get

        Button makeBtn = _root.Q<Button>("MakeBtn");
        Button deleteBtn = _root.Q<Button>("DeleteBtn");
        Button renameBtn = _root.Q<Button>("RenameBtn");
        _itemView = _root.Q<VisualElement>("ItemVisualList");
        selectedLabel = _root.Q<Label>("NameLabel");
        fileNameField = _root.Q<TextField>("FileName");
        _typeOfItem = _root.Q<EnumFlagsField>("TypeOfItem");
        _descriptionField = _root.Q<TextField>("Description");
        _spriteField = _root.Q<ObjectField>("SpriteField");
        _endImmediatelyToggle = _root.Q<Toggle>("EndImmediatelyToggle");
        _EffectEndTime = _root.Q<IntegerField>("EffectEndTime");
        _healCountField = _root.Q<IntegerField>("HealCount");
        _damageCountField = _root.Q<IntegerField>("DamageCount");
        _defenceDecreaseField = _root.Q<IntegerField>("DefenceDesrease");
        _defenceIncreaseField = _root.Q<IntegerField>("DefenceIncrease");
        _strengthField = _root.Q<IntegerField>("Strength");
        _weaknessField = _root.Q<IntegerField>("Weakness");
        _valueList = _root.Q<VisualElement>("ValueList");
        
        #endregion

        _valueList.visible = false;
        
        // ViewItem을 Table에 들어있는 Prefab의 갯수만큼 실행
        if (_itemDataTable.ItemList.Count > 0)
        {
            foreach(var item in _itemDataTable.ItemList){
                ViewItem(item.name);
            }
        }

        makeBtn.clicked += HandleMakeBtnClickEvent;
        deleteBtn.clicked += HandleDeleteBtnClickEvent;
        renameBtn.clicked += HandleRenameBtnClickEvent;
    }

    private void HandleRenameBtnClickEvent()
    {
        ItemSOBase exist =
            AssetDatabase.LoadAssetAtPath<ItemSOBase>(
                $"{_itemFilePath}/{_selected.name}.asset");
        
        exist.itemName = fileNameField.text;
        AssetDatabase.RenameAsset($"{_itemFilePath}/{_selected.name}.asset",
            fileNameField.text);
        
        _itemView.Remove(_selected);
        ViewItem(fileNameField.text);
    }

    private void HandleDeleteBtnClickEvent()
    {
        if (_selected == null)
        {
            Debug.LogError("Select None");
            return;
        }
        
        // 선택된 Item 삭제
        ItemSOBase item = AssetDatabase.LoadAssetAtPath<ItemSOBase>($"{_itemFilePath}/{_selected.name}.asset");

        VisualElement deleteElement = _itemView.Q<VisualElement>(_selected.name);
        _itemView.Remove(deleteElement);

        _itemDataTable.ItemList.Remove(item);
        AssetDatabase.DeleteAsset($"{_itemFilePath}/{_selected.name}.asset");
        EditorUtility.SetDirty(_itemDataTable);
        AssetDatabase.SaveAssets();
        
        _valueList.visible = false;
    }

    private void HandleMakeBtnClickEvent()
    {
        Guid typeGuid = Guid.NewGuid();
        ItemSOBase newItem = ScriptableObject.CreateInstance<ItemSOBase>();
        newItem.name = typeGuid.ToString();
        newItem.itemName = typeGuid.ToString();
        
        AssetDatabase.CreateAsset(newItem,
            $"{_itemFilePath}/{newItem.name}.asset");
        
        
        _itemDataTable.ItemList.Add(newItem);
        
        Debug.
            Log($"Scucess Create Item, Name : {newItem.name} Path : {_itemFilePath}/{newItem.name}.asset");
        
        EditorUtility.SetDirty(_itemDataTable);
        AssetDatabase.SaveAssets();
        
        ViewItem(newItem.name);
    }

    private void OnEnable()
    {
        _ShowItemEvent += ViewItem;
        _viewLabelDictionary = new();

        ValueListBinding(null);
    }
    
    private void OnDisable()
    {
        _ShowItemEvent -= ViewItem;
        DestroyImmediate(_cachedEditor);
    }

    [MenuItem("Tools/LJS/ItemCreater")]
    public static void ShowExample()
    {
        ItemCreater wnd = GetWindow<ItemCreater>();
        wnd.titleContent = new GUIContent("ItemCreater");
        
        Rect main = EditorGUIUtility.GetMainWindowPosition();
        
        wnd.minSize = new Vector2(width, height);
        wnd.maxSize = new Vector2(width, height);
        wnd.position = new Rect((main.width - width) * 0.5f, (main.height - height) * 0.5f, width, height);
    }
    
    // TableSO에 들어있는 Prefab을 VisualElement으로 표현하는 함수이다.
    public void ViewItem(string vName){
        VisualElement element = new VisualElement();
        element.AddToClassList(_itemVisual);
        element.name = vName;
        
        // Mouse Down Event
        element.RegisterCallback<PointerDownEvent>(ElementPointerDownEvent);

        Label label = new Label();
        label.name = "label";
        label.AddToClassList(_itemLabel);
        label.text = vName;
        
        _viewLabelDictionary.Add(vName, label);
        element.Add(label);
        _itemView.Add(element);
    }
    
    private void ElementPointerDownEvent(PointerDownEvent evt)
    {
        bool selected = false;
        foreach(var item in _itemDataTable.ItemList){
            VisualElement element = _root.Q<VisualElement>(item.name);
            List<string> classNames = element.GetClasses().ToList();
            
            // 모든 SelectEffect가 적용된 VisualElement에 Effect를 제거한다.
            foreach(string str in classNames){
                if(str == _itemVisualSelect){
                    element.AddToClassList(_itemVisual);
                    element.RemoveFromClassList(_itemVisualSelect);
                }
            }
            
            // 클릭한 위치의 VisualElement와 현재 Element가 같다면? 그 VisualElement에 Effect를 부여하고
            // Toolbar Label의 Value를 바꾸어 준다.
            if(evt.currentTarget.GetHashCode() == element.GetHashCode()){
                _selected = element;
                element.RemoveFromClassList(_itemVisual);
                element.AddToClassList(_itemVisualSelect);
                
                selectedLabel.text = element.name;
                selected = true;
                ValueListBinding(item);
            }
        }

        if (selected) _valueList.visible = true;
        else _valueList.visible = false;
    }

    private void ValueListBinding(ItemSOBase item)
    {
        // Binding
        
        SerializedObject serializedObject = new SerializedObject(item);
        
        _root.Unbind();
        _root.Bind(serializedObject);
        
        fileNameField.Bind(serializedObject);
        _typeOfItem.Bind(serializedObject);
        _descriptionField.Bind(serializedObject);
        _spriteField.Bind(serializedObject);
        _endImmediatelyToggle.Bind(serializedObject);
        _EffectEndTime.Bind(serializedObject);
        _healCountField.Bind(serializedObject);
        _damageCountField.Bind(serializedObject);
        _defenceDecreaseField.Bind(serializedObject);
        _defenceIncreaseField.Bind(serializedObject);
        _strengthField.Bind(serializedObject);
        _weaknessField.Bind(serializedObject);
                
        fileNameField.bindingPath = "itemName";
        _typeOfItem.bindingPath = "typeOfItem";
        _descriptionField.bindingPath = "description";
        _spriteField.bindingPath = "icon";
        _endImmediatelyToggle.bindingPath =  "endImmediately";
        _EffectEndTime.bindingPath = "effectEndTime";
        _healCountField.bindingPath = "healCount";
        _damageCountField.bindingPath = "damageCount";
        _defenceDecreaseField.bindingPath = "defenceDecrease";
        _defenceIncreaseField.bindingPath = "defenceIncrease";
        _strengthField.bindingPath = "strength";
        _weaknessField.bindingPath = "weakness";
    }
}
.custom-label {
    font-size: 20px;
    -unity-font-style: bold;
    color: rgb(68, 138, 255);
}

.unity-two-pane-split-view__dragline-anchor {
    width: 0;
    height: 0;
    display: none;
    visibility: hidden;
    overflow: visible;
    opacity: 0;
}

.unity-base-text-field__label {
    left: 7px;
    font-size: 15px;
    -unity-font-definition: url("project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&guid=57d31f5b8589fcb4685194f4e84723b1&type=3#DNFForgedBlade-Medium");
    flex-grow: 0;
}

.unity-enum-flags-field__label {
    font-size: 15px;
    -unity-font-definition: url("project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&guid=57d31f5b8589fcb4685194f4e84723b1&type=3#DNFForgedBlade-Medium");
    width: 10px;
}

.unity-enum-flags-field__input {
    left: -8px;
}

.description-label {
}

.unity-text-field__input {
    -unity-text-align: upper-left;
    white-space: normal;
    text-overflow: clip;
}

.unity-object-field__label {
    -unity-font-definition: url("project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&guid=57d31f5b8589fcb4685194f4e84723b1&type=3#DNFForgedBlade-Medium");
    font-size: 15px;
    left: 7px;
}

.unity-toggle__label {
    -unity-font-definition: url("project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&guid=57d31f5b8589fcb4685194f4e84723b1&type=3#DNFForgedBlade-Medium");
    font-size: 15px;
}

.unity-popup-field__label {
    font-size: 15px;
    left: 6px;
    -unity-font-definition: url("project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&guid=57d31f5b8589fcb4685194f4e84723b1&type=3#DNFForgedBlade-Medium");
}

.unity-integer-field__input {
    left: 40px;
    flex-grow: 1;
    width: 0;
    height: auto;
}

.toolbar-btn {
    background-color: rgb(91, 91, 91);
    -unity-font: url("project://database/Library/unity%20default%20resources?fileID=10102&guid=0000000000000000e000000000000000&type=0#LegacyRuntime");
}

.default-Label {
}

.item-visual {
    flex-grow: 1;
    height: 30px;
    border-bottom-width: 1px;
    border-left-color: rgb(40, 40, 40);
    border-right-color: rgb(40, 40, 40);
    border-top-color: rgb(40, 40, 40);
    border-bottom-color: rgb(40, 40, 40);
}

.item-label {
    justify-content: center;
    align-items: center;
    -unity-text-align: middle-left;
    flex-direction: column;
    flex-wrap: nowrap;
    flex-shrink: 1;
    align-self: flex-start;
    flex-grow: 1;
    left: 5px;
    -unity-font-definition: url("project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&guid=57d31f5b8589fcb4685194f4e84723b1&type=3#DNFForgedBlade-Medium");
}

.item-visual:hover {
    border-left-color: rgba(0, 0, 0, 0);
    border-right-color: rgba(0, 0, 0, 0);
    border-top-color: rgba(0, 0, 0, 0);
    border-bottom-color: rgba(0, 0, 0, 0);
    background-color: rgb(66, 66, 66);
    transition-duration: 0s;
}

.item-visual-select {
    flex-grow: 1;
    height: 30px;
    border-bottom-width: 1px;
    border-left-color: rgb(40, 40, 40);
    border-right-color: rgb(40, 40, 40);
    border-top-color: rgb(40, 40, 40);
    border-bottom-color: rgb(40, 40, 40);
    background-color: rgb(62, 95, 150);
}
<engine:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:engine="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
    <Style src="project://database/Assets/00Work/LJS/10_UI/ItemCreater.uss?fileID=7433441132597879392&amp;guid=5ec1da0135e453047b5fa8281e46bce6&amp;type=3#ItemCreater" />
    <Style src="project://database/Assets/00Work/LJS/10_UI/MakePrefabWindow.uss?fileID=7433441132597879392&amp;guid=4d8bf05f45ec2884e9c0cbfe150365af&amp;type=3#MakePrefabWindow" />
    <SplitView style="width: 900px; height: 700px; flex-basis: 900px;">
        <engine:VisualElement name="SerachTab" style="flex-grow: 0; width: 0; flex-basis: 250px; border-left-color: rgb(42, 42, 42); border-right-color: rgb(42, 42, 42); border-top-color: rgb(42, 42, 42); border-bottom-color: rgb(42, 42, 42); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px;">
            <engine:ScrollView name="ItemVisualTable" style="bottom: -1px; flex-grow: 1;">
                <editor:ToolbarPopupSearchField name="ItemSerachBar" style="width: 242px; border-left-color: rgb(42, 42, 42); border-right-color: rgb(42, 42, 42); border-top-color: rgb(42, 42, 42); border-bottom-color: rgb(42, 42, 42);" />
                <engine:VisualElement name="ItemVisualList" focusable="true" style="flex-grow: 1;" />
            </engine:ScrollView>
        </engine:VisualElement>
        <engine:VisualElement name="InfoTab" style="flex-grow: 0; border-left-color: rgba(42, 42, 42, 0); border-right-color: rgba(42, 42, 42, 0); border-top-color: rgba(42, 42, 42, 0); border-bottom-color: rgba(42, 42, 42, 0);">
            <editor:Toolbar name="Toolbar" style="border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-left-color: rgb(42, 42, 42); border-right-color: rgb(42, 42, 42); border-top-color: rgb(42, 42, 42); border-bottom-color: rgb(42, 42, 42); height: 30px; width: 650px; left: -1px; flex-direction: row;">
                <engine:Label text="Label" name="NameLabel" style="right: 100px; bottom: -3px; font-size: 18px; -unity-font-definition: url(&quot;project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&amp;guid=57d31f5b8589fcb4685194f4e84723b1&amp;type=3#DNFForgedBlade-Medium&quot;); width: 330px; left: 10px;" />
                <engine:Button text="Delete" name="DeleteBtn" style="width: 100px; -unity-font-definition: url(&quot;project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&amp;guid=57d31f5b8589fcb4685194f4e84723b1&amp;type=3#DNFForgedBlade-Medium&quot;);" />
                <engine:Button text="Create" name="MakeBtn" style="width: 100px; -unity-font-definition: url(&quot;project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&amp;guid=57d31f5b8589fcb4685194f4e84723b1&amp;type=3#DNFForgedBlade-Medium&quot;);" />
                <engine:Button text="Rename" name="RenameBtn" selectable="true" style="width: 100px; -unity-font-definition: url(&quot;project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&amp;guid=57d31f5b8589fcb4685194f4e84723b1&amp;type=3#DNFForgedBlade-Medium&quot;);" />
            </editor:Toolbar>
            <engine:VisualElement name="ValueList" style="flex-grow: 1;">
                <engine:VisualElement name="FristHeader" style="flex-grow: 0.6; height: 0;">
                    <engine:Label text="BaseInfo" name="Label" style="font-size: 20px; left: 7px; -unity-font-definition: url(&quot;project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&amp;guid=57d31f5b8589fcb4685194f4e84723b1&amp;type=3#DNFForgedBlade-Medium&quot;);" />
                    <engine:TextField label="FileName" name="FileName" data-source="project://database/Assets/00Work/LJS/05_SO/Item/HealPotion.asset?fileID=11400000&amp;guid=238c5ca49f5997a47ab7a07328f1db10&amp;type=2#HealPotion" data-source-path="itemName" />
                    <editor:EnumFlagsField label="TypeOfItem" value="None" type="LJS.Item.ItemType, LJS.Item" name="TypeOfItem" style="left: 6px;" />
                    <engine:TextField label="Description" multiline="true" vertical-scroller-visibility="Auto" name="Description" style="flex-direction: column; height: 100px;" />
                    <editor:ObjectField label="Sprite" type="UnityEngine.Sprite, UnityEngine.CoreModule" name="SpriteField" />
                </engine:VisualElement>
                <engine:VisualElement name="EffectSetting" style="flex-grow: 0.1;">
                    <engine:Label text="EffectSetting" style="top: 0; left: 7px; -unity-text-align: upper-left; font-size: 20px; -unity-font-definition: url(&quot;project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&amp;guid=57d31f5b8589fcb4685194f4e84723b1&amp;type=3#DNFForgedBlade-Medium&quot;);" />
                    <engine:Toggle label="End immediately" name="EndImmediatelyToggle" style="top: 0; left: 5px;" />
                    <engine:IntegerField label="Effect End Time" value="0" name="EffectEndTime" style="top: 0;" />
                </engine:VisualElement>
                <engine:VisualElement name="EffectValue" style="flex-grow: 0.3; top: 1px;">
                    <engine:Label text="Effect Value" style="top: 0; left: 7px; -unity-text-align: upper-left; font-size: 20px; -unity-font-definition: url(&quot;project://database/Assets/00Work/LJS/04_Font/DNFForgedBlade-Medium.ttf?fileID=12800000&amp;guid=57d31f5b8589fcb4685194f4e84723b1&amp;type=3#DNFForgedBlade-Medium&quot;);" />
                    <engine:IntegerField label="HealCount" value="0" name="HealCount" style="left: 0;" />
                    <engine:IntegerField label="DamageCount" value="0" name="DamageCount" />
                    <engine:IntegerField label="DefenceDesrease" value="0" hide-mobile-input="false" name="DefenceDesrease" style="height: auto;" />
                    <engine:IntegerField label="DefenceIncrease" value="0" name="DefenceIncrease" style="align-items: auto;" />
                    <engine:IntegerField label="Strength" value="0" name="Strength" />
                    <engine:IntegerField label="Weakness" value="0" name="Weakness" style="bottom: auto;" />
                </engine:VisualElement>
            </engine:VisualElement>
        </engine:VisualElement>
    </SplitView>
</engine:UXML>

 

설명은 CS 만 하겠다.

중요한 구간으로는 Binding, Make, ViewItem, Delete, Rename이 있다. 하나씩 설명하겠다.

 

Make

private void HandleMakeBtnClickEvent()
{
    Guid typeGuid = Guid.NewGuid();
    ItemSOBase newItem = ScriptableObject.CreateInstance<ItemSOBase>();
    newItem.name = typeGuid.ToString();
    newItem.itemName = typeGuid.ToString();

    AssetDatabase.CreateAsset(newItem,
        $"{_itemFilePath}/{newItem.name}.asset");


    _itemDataTable.ItemList.Add(newItem);

    Debug.
        Log($"Scucess Create Item, Name : {newItem.name} Path : {_itemFilePath}/{newItem.name}.asset");

    EditorUtility.SetDirty(_itemDataTable);
    AssetDatabase.SaveAssets();

    ViewItem(newItem.name);
}

새로운 Guid를 생성해준다. 이름을 랜덤으로 생성하기 위해서이다.  그다음에 CreateInstacne 함수를 사용하여 새로운 ItemSOBase를 하나 만들어준다. 이름과 ItemName 변수는 Guid로 해준다. 그다음에 생성한 SO를 실제 파일로도 만들어 준다. 리스트에도 추가해주고 SetDirty와 SaveAssets를 해준 다음 Visual이 Window에 보여야 하기 때문에 viewItem 함수를 실행시켜준다.

 

ViewItem

public void ViewItem(string vName){
    VisualElement element = new VisualElement();
    element.AddToClassList(_itemVisual);
    element.name = vName;

    // Mouse Down Event
    element.RegisterCallback<PointerDownEvent>(ElementPointerDownEvent);

    Label label = new Label();
    label.name = "label";
    label.AddToClassList(_itemLabel);
    label.text = vName;

    _viewLabelDictionary.Add(vName, label);
    element.Add(label);
    _itemView.Add(element);
}

VisualElement를 만들고 이미 있는 Class를 추가해서 비주얼을 맞춰준다. 그리고 이때 RegistreCallBack으로 PointerDownEvent를 등록해준다 (마우스 클릭 이벤트임)

그다음에 라벨을 생성시켜주고 Element의 자식으로 한뒤 Table에도 넣고 Dict에도 넣어준다. 그럼 끝!

 

Delete

private void HandleDeleteBtnClickEvent()
{
    if (_selected == null)
    {
        Debug.LogError("Select None");
        return;
    }

    // 선택된 Item 삭제
    ItemSOBase item = AssetDatabase.LoadAssetAtPath<ItemSOBase>($"{_itemFilePath}/{_selected.name}.asset");

    VisualElement deleteElement = _itemView.Q<VisualElement>(_selected.name);
    _itemView.Remove(deleteElement);

    _itemDataTable.ItemList.Remove(item);
    AssetDatabase.DeleteAsset($"{_itemFilePath}/{_selected.name}.asset");
    EditorUtility.SetDirty(_itemDataTable);
    AssetDatabase.SaveAssets();

    _valueList.visible = false;
}

현재 선택한 것이 없다면 반환 해준다. 만약 있다면 Load 해준다. 그리고 element를 찾고 현재 View에서 지워준다 그리고 Table에서도 지워준다 그다음 실제로 경로를 따라가서 Asset을 지워주고 Dirty와 SaveAssets를 해준다. (_valueList는 Inspector 처럼 띄워주는 정보 창이다. 지웠으니까 정보가 보이면 안되니 false로 안보여준다.)

 

Rename

private void HandleRenameBtnClickEvent()
{
    ItemSOBase exist =
        AssetDatabase.LoadAssetAtPath<ItemSOBase>(
            $"{_itemFilePath}/{_selected.name}.asset");

    exist.itemName = fileNameField.text;
    AssetDatabase.RenameAsset($"{_itemFilePath}/{_selected.name}.asset",
        fileNameField.text);

    _itemView.Remove(_selected);
    ViewItem(fileNameField.text);
}

간단하다, 현재 선택된 SO의 이름을 통해서 Load를 하고 이름과 ItemName을 바꿔주면 된다. 그리고 정보 갱신을 위해서 Eelement를 지우고 다시 생성해준다.

 

private void ValueListBinding(ItemSOBase item)
    {
        // Binding
        
        SerializedObject serializedObject = new SerializedObject(item);
        
        _root.Unbind();
        _root.Bind(serializedObject);
        
        fileNameField.Bind(serializedObject);
        _typeOfItem.Bind(serializedObject);
        _descriptionField.Bind(serializedObject);
        _spriteField.Bind(serializedObject);
        _endImmediatelyToggle.Bind(serializedObject);
        _EffectEndTime.Bind(serializedObject);
        _healCountField.Bind(serializedObject);
        _damageCountField.Bind(serializedObject);
        _defenceDecreaseField.Bind(serializedObject);
        _defenceIncreaseField.Bind(serializedObject);
        _strengthField.Bind(serializedObject);
        _weaknessField.Bind(serializedObject);
                
        fileNameField.bindingPath = "itemName";
        _typeOfItem.bindingPath = "typeOfItem";
        _descriptionField.bindingPath = "description";
        _spriteField.bindingPath = "icon";
        _endImmediatelyToggle.bindingPath =  "endImmediately";
        _EffectEndTime.bindingPath = "effectEndTime";
        _healCountField.bindingPath = "healCount";
        _damageCountField.bindingPath = "damageCount";
        _defenceDecreaseField.bindingPath = "defenceDecrease";
        _defenceIncreaseField.bindingPath = "defenceIncrease";
        _strengthField.bindingPath = "strength";
        _weaknessField.bindingPath = "weakness";
    }

이번에 6에 처음 나온 Binding 기법이다. 기존의 Binding 방법이 어렵다고 판단하여 Elemet에 직접 Bind 함수를 추가하여 SerilzedObject라면 뭐든지 Binding 할 수 있게 하였다. (보통 SO랑 연결함, 대신 Serilazed 안되어 있다면 연결이 불가능함) 방법은 RootEelement한테 SO로 직접 바인드 하고 필요한 녀석들한테 따로따로 Bind 해주면 된다. 그리고 Path를 통해서 변수의 값을 들고 온다. (변수명과 동일한 이름 적으면 됨) Binding 하고 싶은 SO는 IBinding을 상속 받아야한다.

 

이번에 새로 나온 Serialzed Object Binding은 편하고 좋긴 한데 너무 가독성이 떨어지는 감이 있다. 따라서 프로퍼티 드로어를 사용하는 편이 좋아보인다. 아마 성능도 비슷하고 코드도 간결 해질 거다

 

 

앞으로 추가하거나 수정해야할 부분은 Sprite의 미리보기 기능을 추가하고 List를 추가를 안했는데 해야 함 저거만 하면 끝일듯...

'Editor' 카테고리의 다른 글

[Unity, Editor] SOManagementWindow 제작 일기 Part.2  (0) 2025.04.25
[Unity, Editor] SOManagementWindow 제작 일기 Part.1  (0) 2025.04.25
[Editor] 적 생성 Editor Window 코드 부분 제작  (0) 2024.10.10
[Editor] 적 생성 Editor Window 제작 과정 part.2  (0) 2024.10.08
[Editor] 적 생성 Editor Window 제작 과정 part.1  (1) 2024.10.07
'Editor' 카테고리의 다른 글
  • [Unity, Editor] SOManagementWindow 제작 일기 Part.2
  • [Unity, Editor] SOManagementWindow 제작 일기 Part.1
  • [Editor] 적 생성 Editor Window 코드 부분 제작
  • [Editor] 적 생성 Editor Window 제작 과정 part.2
HK1206
HK1206
고3 게임 개발자의 개발 일지
  • HK1206
    GGM-LJS
    HK1206
  • 전체
    오늘
    어제
    • 분류 전체보기 (25) N
      • Unity (16)
      • Shader (1)
      • Editor (8) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
HK1206
[졸업 작품, Unity]Item EditorWindow로 관리하기
상단으로

티스토리툴바