РЕДАКТИРОВАТЬ: ПРОБЛЕМА БЫЛА ЭТОЙ ЛИНИИ: = новый список (10). Комментируя это и добавляя атрибут SerializeField, похоже, справляется с работой
В Unity3D я пытаюсь создать простой скрипт для создания меню, который помог бы мне создавать меню для моей игры.
Я создалкласс, который содержит элементы подменю в списке и создал собственный инспектор для класса, чтобы я мог легко удалить элементы из списка.
Моя проблема в том, что когда я закрываю сцену, список не сохраняется. Я не создавал пользовательских инспекторов раньше, поэтому я не уверен, что делаю это правильно.
Это мой код: (РЕДАКТИРОВАТЬ: попытался добавить [SerializeField, HideInInspector] в список, и он сохранилсписок, но ссылки потерялись ...)
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class MenuController : MonoBehaviour
{
[SerializeField] private MenuSettings menuSettings; // Only holds reference to the MenuController prefab
[SerializeField] private string text;
[SerializeField] private BackgroundController subMenuItemsHolder;
[SerializeField, HideInInspector] private List<MenuController> subMenuItems/* = new List<MenuController>(10)*/;
public byte SubMenusCount => (byte)subMenuItems.Count;
public string Text
{
get => text;
set
{
if (!string.IsNullOrEmpty(value))
{
text = value;
}
}
}
public MenuController GetSubMenuAtIndex(byte index)
{
if (!IsIndexValid(index))
{
throw new System.ArgumentOutOfRangeException(nameof(index));
}
return subMenuItems[index];
}
public void AddSubMenu(string text)
{
MenuController subMenu = menuSettings.CreateInstance(subMenuItemsHolder.transform); // Just calling Instantiate
subMenu.Text = text;
subMenu.name = text;
subMenuItems.Add(subMenu);
}
public void RemoveSubMenuAtIndex(byte index, bool destroy = true)
{
if (!IsIndexValid(index))
{
throw new System.ArgumentOutOfRangeException(nameof(index));
}
if (destroy)
{
if (Application.isPlaying)
{
Destroy(subMenuItems[index].gameObject);
}
else
{
UnityEditor.Undo.DestroyObjectImmediate(subMenuItems[index].gameObject);
}
}
subMenuItems.RemoveAt(index);
}
private bool IsIndexValid(byte index)
{
return index >= 0 && index < subMenuItems.Count;
}
}
И код для специального инспектора:
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(MenuController))]
public class MenuControllerEditor : Editor
{
private MenuController menuController;
private string newSubMenuText = string.Empty;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
GUILayout.Space(10);
byte count = menuController.SubMenusCount;
MenuController subMenuItem;
GUILayout.Label($"Sub menu items count: {count}");
for (byte i = 0; i < count; i++)
{
subMenuItem = menuController.GetSubMenuAtIndex(i);
Undo.RecordObject(subMenuItem, "Changed sub menu item's text");
GUILayout.BeginHorizontal();
subMenuItem.Text = GUILayout.TextField(subMenuItem.Text, GUILayout.MinWidth(200), GUILayout.ExpandWidth(true));
if (GUILayout.Button("X", GUILayout.Width(50)))
{
menuController.RemoveSubMenuAtIndex(i);
menuController.RefreshLayout();
GUILayout.EndHorizontal();
return;
}
GUILayout.EndHorizontal();
}
subMenuItem = null;
GUILayout.Space(10);
GUILayout.BeginHorizontal();
Undo.RecordObject(menuController, "Changed new sub menu text");
newSubMenuText = GUILayout.TextField(newSubMenuText, GUILayout.MinWidth(200), GUILayout.ExpandWidth(true));
if (GUILayout.Button("Add", GUILayout.Width(50)))
{
menuController.AddSubMenu(newSubMenuText.Trim());
menuController.RefreshLayout();
newSubMenuText = string.Empty;
}
GUILayout.EndHorizontal();
}
private void OnEnable()
{
menuController = (MenuController)target;
}
private void OnDisable()
{
menuController = null;
}
}