Удобное решение для игровой базы данных на основе EditorWindow

в 9:36, , рубрики: database tools, EditorWindow, unity3d

Unity предлагает отличные инструменты для создания небольших игр с малым количеством переменных. Когда проект разрастается, становится крайне неудобно изменять в стандартном Inspector данные, особенно если все данные хранятся в одном месте (что крайне удобно при редактировании).

image

Как сделать удобную для редактирования и понятную для геймдизайнеров базу данных?
Об этом ниже.

Для начала создадим класс DataBase который будет отвечать за общение с базой данных или хранение данных для небольших проектов.

Стоит поговорить с гемдизайнором и определится какой список типов данных потребуется. Для примера это будет 4 типа данных.

Записываем их в enum (потом будет понятно зачем)

public enum DataType
{
    Item=0,
    Ship=1,
    Spell=2,
    Recipe=3,
}

Тут-же создаем интерфейс для общения с нашими типами данных. В нем обязательными полями должны быть Id, Name и одна функция DrawGui() которая в дальнейшем и будет отвечать за отрисовку нашего интерфейса.


public interface IData
{
    int Id { get; set; }
    string Name { get; set; }

#if UNITY_EDITOR
    void DrawGui();
#endif
}

Функция DrawGui() нам не нужна в скомпилированном проекте так что ее настоятельно рекомендую обнести директивой компиляции.

В самом классе DataBase добавляем функции для доступа к данным:

List GetDatas(DataType type) — для получения всего списка данных указанного типа
IData GetData(DataType type, int id) — для получения данных по id
void AddData(DataType type) — добавления нового значения
void UpdateData(DataType type, IData data) — обновление указанного значения
void Remove(DataType type, int id) — удаления указанного значения

В этих функциях будет описано взаимодействие с базой данных например с PostgreSQL.

Получилось вот так

image

Теперь надо создать класс для отрисовки окна в редакторе Unity. Создаем папку Editor и в ней скрипт DataBaseEditor. Наследуем его от EditorWindow.

Нужно реализовать переключение между созданными ранее типами данных.

Объявим статичную переменную DataType CurrentDataType и сделаем выбор типа данных в стандартной функции OnGUI()

Тут есть 2 варианта:

  • воспользоваться стандартным EditorGUILayout.EnumPopup()
  • для каждого элементы enum создать свою кнопку

Лично я предпочитаю второй вариант так получается удобнее. Вот такого кода вполне достаточно

  var types = Enum.GetValues(typeof (DataType));
        GUILayout.BeginHorizontal();
        foreach (var type in types)
        {
            if (GUILayout.Button(type.ToString()))
            {
                CurrentDataType = (DataType) type;
            }
        }
        GUILayout.EndHorizontal();

Можно немного поиграть и сделать выделение выбранного типа цветом.

Теперь добавим одну кнопку для добавления данных в нашу базу данных

 if (GUILayout.Button("Add"))
        {
            DataBase.AddData(CurrentDataType);
        }

И осталось вызвать наше окно из меню Unity для этого:

  1. создаем новый элемент меню [MenuItem("DataBase/EditDataBase")]
  2. по клику на элемент меню создаем наше окно

  static void Init()
    {
        var window = (DataBaseEditor)GetWindow(typeof(DataBaseEditor));
        window.Show();
    }

В результате должно получится что-то такое

image

Теперь нам нужно окошко в котором будет отображаться сама форма для изменения данных.

Создаем новый класс DataWindowEditor и как и ранее наследуем его от EditorWindow.

В этом классе нам нужно отследить 2 события (открытие и закрытие окна).

При открытии будем передавать этому окну данные для отображения и сохранять ранее открытые данные чтоб геймдизайнер случайно не потерял свою работу.

При закрытии сохранять изменения в нашу базу данных.


 public void OnOpen(IData data,DataType type)
    {
        if (_data != null)
        {
            DataBaseEditor.DataBase.UpdateData(_dataType, _data);
        }
        _data = data;
        _dataType = type;
    }

  void OnDestroy()
    {
        DataBaseEditor.DataBase.UpdateData(_dataType, _data);
    }

И осталось нарисовать саму форму в OnGUI


 public void OnGUI()
    {
        if (_data==null)
        {
            Close();
            return;
        }
        _data.DrawGui();
    }

Теперь нам надо получить список наших данных. Воспользуемся ранее созданной функцией GetDatas.

И отрисовываем наши данные средствами GUILayout, при клике на элемент открыть его представление.


  var datas = DataBase.GetDatas(CurrentDataType);
        foreach (var data in datas)
        {
            GUILayout.BeginHorizontal();
            if (GUILayout.Button("Id: " + data.Id + " Name: " + data.Name))
            {
                var window = (DataWindowEditor)GetWindow(typeof(DataWindowEditor));
                window.OnOpen(data,CurrentDataType);
                window.Show();
            }
            if (GUILayout.Button("-"))
            {
                DataBase.Remove(CurrentDataType,data.Id);
            }
            GUILayout.EndHorizontal();
        }

Вторая кнопка отвечает за удаление указанного элемента.

Теперь перейдем непосредственно к нашим данным.

Создадим новый класс Item.

Добавляем поля, нужные геймдизайнеру.

В моем случае пока это будет цена предмета.

Наследуем класс от ранее созданного интерфейса IData.

Функцию DrawGui() как и в интерфейсе стоит пометить директивой условной компиляции и в теле функции описать само отображение элемента:


#if UNITY_EDITOR

    public void DrawGui()
    {

        GUILayout.Label("Id: "+Id);
        Name = EditorGUILayout.TextField("Name: " , Name);

        Price = EditorGUILayout.IntField("Price: " , Price);
    }

#endif

На этом все. Переходим в редактор и получаем вот такую картинку:

image

Для остальных типов данных так-же создаем отдельные классы и делаем все тоже само что и для класса Item.

Автор: Blackelf2

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js