2017-02-22 38 views
3

Я создаю специальный редактор для создания и уничтожения нескольких объектов с помощью двух кнопок графического интерфейса. В режиме редактирования все работает нормально, я могу создавать несколько сборных файлов, а затем уничтожать их один за другим, начиная с последнего экземпляра, но как только я нажимаю «Play» и «Stop», я не могу уничтожить любые ранее созданные экземпляры prefabs (создаваемые в режиме воспроизведения). Я могу создавать новые сборные файлы, а затем уничтожать их, но что касается тех сборников, которые были созданы, прежде чем я нажму игру, они остаются без изменений.Пользовательский редактор сбрасывает после игры?

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

Всякий раз, когда создается экземпляр prefab, я добавляю его в стек и сохраняю дорожку размера. После того, как я нажал кнопку play-stop, кажется, что он сбрасывается до 0.

После просмотра многочисленных сообщений о подобной проблеме и проверке API Unity, я понимаю, что мне нужно выяснить способ сохранения настроек и переменных настраиваемого редактора путем сериализации их или сделать их грязными, я просто не знаю, как это сделать. Я пробовал то, что предлагалось в этих сообщениях, но в моем случае ничего не работает (или я делаю что-то неправильно).

У меня есть сценарий Monobehaviour и сценарий редактора. Я опубликую фрагменты для одного типа объекта, так как другие части одинаковы.

Вот первый:

using System.Collections; 
using System.Collections.Generic; 
using UnityEngine; 

[System.Serializable, ExecuteInEditMode] 
    public class ObjectControl: MonoBehaviour { 

[SerializeField, HideInInspector] 
public Stack<GameObject> undoStack = new Stack<GameObject>(); 
public GameObject instance; 
public int undoStackSize; 
public int objectSelectionIndex = 0; 

public void placeObject() 
{ 
    switch (objectSelectionIndex) 
    { 
     case 1: 

      Debug.Log("Just received a number 1 from the editor"); 
      GameObject object_A = Resources.Load("Prefabs/Object_A") as GameObject; 
      instance = Instantiate(object_A, this.transform.position, this.transform.rotation, this.transform); 

      undoStack.Push(instance); 
      undoStackSize = undoStack.Count; 

      break; 

     case 4: 

      Debug.Log("Just received a number 4 from the editor, deleting the object"); 

      if (undoStack.Count > 0) 
      { 
       GameObject objToUndo = undoStack.Pop(); 
       DestroyImmediate(objToUndo); 
       undoStackSize--; 

      } 

      else 
      { 
       Debug.Log("Stack is empty! Stack size is: " + undoStack.Count); 
      } 

      break; 
    } 
} 

И редактор сценария:

using UnityEngine; 
using System.Collections; 
using UnityEditor; 
using System.Collections.Generic; 


[CustomEditor(typeof(ObjectControl)), CanEditMultipleObjects] 
public class ObjectControlEditor : Editor 
{ 

int objectSelectionToolbar = 0; 
int numberOfPossibleUndo; 

bool chooseOption = false; 
bool objectSelectionFoldout = false; 

public ObjectControl scriptTarget; 

public void Awake() 
{ 
    scriptTarget = (ObjectControl)target; 
} 

public override void OnInspectorGUI() 
{ 
    DrawDefaultInspector(); 

    GUI.changed = false; 

    chooseOption = EditorGUILayout.Foldout(chooseOption, "Choose a segment to add:"); 

    if (chooseOption) 
    { 

     EditorGUILayout.BeginVertical(); 

     stationSelectionFoldout = GUILayout.Toggle(stationSelectionFoldout, "" + (stationSelectionFoldout ? "▼ Object selection ▼" : "► Object selection ◄"), "Button", GUILayout.MaxWidth(Screen.width), GUILayout.Height(25)); 

     if (objectSelectionFoldout) 
     { 

      GUILayout.Space(5);  //Space before a text box 
      GUILayout.Box("Select lenght of the station:"); 
      GUILayout.Space(5);  //Space after a text box and before a toolbox 

      string[] objectSelectionToolbarOptions = new string[] { "Object A", "Object B", "Object C" }; 

      stationSelectionToolbar = GUILayout.Toolbar(objectSelectionToolbar, objectSelectionToolbarOptions, GUILayout.MinWidth(Screen.width), GUILayout.Height(50)); 
      GUILayout.Space(5); 

      RollerCoasterBuilder scriptTarget = (RollerCoasterBuilder)target; 
      numberOfPossibleUndo = scriptTarget.undoStackSize; 

      switch (objectSelectionToolbar) 
      { 
       case 0: 

        GUILayout.BeginHorizontal(); 

        if (GUILayout.Button("Place selected object", GUILayout.Height(30))) 
        { 
         scriptTarget.objectSelectionIndex = 1; 
         scriptTarget.PlaceObject(); 
        } 

        GUILayout.Space(5); 

        if (GUILayout.Button("Undo" + "(" + numberOfPossibleUndo + ")", GUILayout.Height(30))) 
        { 
         scriptTarget.objectSelectionIndex = 4; 
         scriptTarget.PlaceObject(); 
        } 

        GUILayout.EndHorizontal(); 

        break; 
       } 
      } 
     } 
    if (GUI.changed) 
     { 
     EditorUtility.SetDirty(target); 
     } 
} 
} 
+0

Не редактируйте свой начальный пост и добавьте [resolved]. Это не так, как работает stackoverflow. Вы должны либо пометить лучший ответ как принимаемый ответ, либо сделать свой собственный лучший ответ. Если вы отбросите проблему и нет хорошего ответа, вы должны удалить вопрос. – JHBonarius

+0

Спасибо J.H.Bonarius, сделаю в следующий раз. –

ответ

1

Единство не может сериализовать тип стека данных. Попробуйте преобразовать ваш undoStack в массив [] или List <>. Здесь вы можете посмотреть список сериализуемых типов: https://docs.unity3d.com/ScriptReference/SerializeField.html

В качестве альтернативы вы можете написать собственную версию serializeble, если Unity еще не поддерживает ее. см.: http://answers.unity3d.com/questions/460727/how-to-serialize-dictionary-with-unity-serializati.html (второй ответ).

Также не забудьте прочитать раздел «ПРИМЕЧАНИЕ» на странице EditorUtility.SetDirty() в API, чтобы убедиться, что ваша текущая реализация не работает против зерна Unity. Я не могу связать его, потому что у меня есть достаточно репутации, чтобы опубликовать 2 ссылки ...

0

Спасибо, Майкл за ваш вклад.

Я решил угробить стека и продолжить с удаления дочерних объектов, один за другим, от последнего до первого, как можно видеть на этом посту: Simple way to Delete the Last Child of a GameObject

Нет больше проблем после плей-режиме:)

Имейте славный день!