1

我有一个有关卡的场景。这个场景有 1000 个级别。它的关卡有一个TextAsset。我想运行一个 EditorScript 并通过脚本而不是通过将 1.000 个 TextAssets 拖放到场景中来分配这些 TextAssets。然后自动保存场景。

Scene mainScene = SceneManager.GetSceneByName("Main");
GameObject[] gameObjects = mainScene.GetRootGameObjects();
GameManager gameManager = gameObjects[0].GetComponent<GameManager>();
List<LanguageCategory> languageCategories = new List<LanguageCategory>();
LanguageCategoryPackInfo l1 = new LanguageCategoryPackInfo();
l1.displayName = "t1";
LanguageCategoryPackInfo l2 = new LanguageCategoryPackInfo();
l2.displayName = "t2";
languageCategories.Add(l1);
languageCategories.Add(l2);
gameManager.LanguageCategoryPackInfos = languageCategories;
//do the same assignment again, but with no luck
mainScene.GetRootGameObjects()[0].GetComponent<GameManager>().LanguageCategoryPackInfos = languageCategories;
EditorSceneManager.SaveScene(mainScene);

运行上述代码后,场景似乎没有改变。

4

1 回答 1

1

The problem with directly making some changes in the component doesn't mark it as dirty and thus changes are not saved! (see also explenation in SerializedObject and solution below.)

You can do this manually using EditorUtility.SetDirty. As noted there you should always combine it with first also calling Undo.RecordObject.

If you don't care about the Undo/Redo functionality you can also simply use EditorSceneManager.MarkSceneDirty

Scene mainScene = SceneManager.GetSceneByName("Main");
GameObject[] gameObjects = mainScene.GetRootGameObjects();
GameManager gameManager = gameObjects[0].GetComponent<GameManager>();

List<LanguageCategory> languageCategories = new List<LanguageCategory>();

LanguageCategoryPackInfo l1 = new LanguageCategoryPackInfo();
l1.displayName = "t1";
LanguageCategoryPackInfo l2 = new LanguageCategoryPackInfo();
l2.displayName = "t2";
languageCategories.Add(l1);
languageCategories.Add(l2);

// record an undo point
Undo.RecordObject(gameManager, "languages added");
gameManager.LanguageCategoryPackInfos = languageCategories;
// mark the object dirty so it will be saved
EditorUtility.SetDirty(gameManager);

// or simply directly
EditorSceneManager.MarkSceneDirty();
EditorSceneManager.SaveScene(mainScene);

As alternative though it is more complex it is always recommended to instead go through the SerializedObject and SerializedPropertys which handles all the marking dirty and undo/redo functionalities for you automatically.

Scene mainScene = SceneManager.GetSceneByName("Main");
GameObject[] gameObjects = mainScene.GetRootGameObjects();
GameManager gameManager = gameObjects[0].GetComponent<GameManager>();

SerializedObject serializedObject = new SerializedObject(gameManager);

SerializedProperty languageCategories = serializedObject.FindProperty("LanguageCategoryPackInfos");

// load the current real values into the serializedObject
serializedObject.Update();

languageCategories.arraySize = 2;

SerializedProperty l1 = languageCategories.GetArrayElementAtIndex(0);
l1.FindPropertyRelative("displayName").stringValue = "t1";
SerializedProperty l2 = languageCategories.GetArrayElementAtIndex(1);
l2.FindPropertyRelative("displayName").stringValue= "t2";

// writes the changes bakc to the actual properties and marks them as dirty etc
serializedObject.ApplyModifiedProperties();

EditorSceneManager.SaveScene(mainScene);

Note: Typed on smartphone so no warrenty, but I hope the idea gets clear

于 2019-07-23T07:11:39.580 回答