Unity talks about imported pictures automatically turning into Sprites and automatically generating switching scene menus

Five months later, I finally remembered that I still have a blog. (If it wasn’t for Double Eleven spending too much money, I might not have calmed down to update [狗头])

Today, I will talk about two functions:
1. Imported pictures are automatically converted into Sprite types, which saves the cumbersome operation of changing the type every time a new picture is imported.
2. The newly created scene can be directly displayed in the tree directory of the menu bar. It eliminates the troublesome problem of finding a new temporary scene when you want to change it back.

First, let's talk about a Unity API AssetPostprocessor,
which is an editor class. The main thing to do is to process these resources after or before you import them.
https://docs.unity3d.com/ScriptReference/AssetPostprocessor.html

Ok, let's start with the first problem.
When you import a picture,
insert image description here
insert image description here
the picture below is in Default format. Your Image component cannot use such images. You need to replace it with Sprite (2D and UI),
although you can select several pictures and modify their types together. But, I just find it annoying.
At this time, the usefulness of the AssetPostprocessor just mentioned comes

Create a new class in the Editor directory and add the following code:

using UnityEditor;
using UnityEngine;

public class AssetPostManager : AssetPostprocessor
{
    
    
    void OnPostprocessTexture(Texture texture)
    {
    
    
        if (assetPath.StartsWith("Assets/Resources/Image"))
        {
    
    
            TextureImporter importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
            if ((importer != null) && (importer.textureType != TextureImporterType.Sprite))
            {
    
    
                importer.textureType = TextureImporterType.Sprite;
                importer.SaveAndReimport();
            }
        }
    }
}

This code should be easy to understand.
First judge the path (for my project, the prefab pictures are all placed here, so I only modify the picture type in this directory).
Then judge, if it is not Sprite, change it to Sprite. It is best to add this type of judgment, because it may affect the data of Jiugongge.
Finally, you must SaveAndReimport() to see that it has been modified.

Well, there's nothing more to say about this thing. Let's start with the second question.
When you are adjusting some models, you like to ctrl+N to create a new unsaved scene to modify. After you have finished the modification, you have to go back to the default starting scene to actually run the game to see the effect. At this time, you have to search for the scene you need all over the world, and when you double-click, your selected resources have also changed, and you have to search for the resources you just adjusted all over the world.
At this time, do you really want to have such a menu:
insert image description here

insert image description here
A menu can be dynamically generated to quickly switch scenes.

Maybe your first reaction is: "I can write a bunch of MenuItems."
Although this statement makes sense, you have to think about it. First, do you have to write it here every time you add a new scene? Secondly, other scenes are generally needed by the art side, so they probably won't write this code.

So for requirements, automation is starting to be useful.
But you may have doubts, does Unity's editor property still support this dynamic number of MenuItem?
I checked it out, and an old man answered as follows:
insert image description here
It clearly pointed out that only Added and Removed are supported, and Adding and Removing are not supported. This understanding means that only when Unity thinks that the DLL needs to be changed, will it recompile these C# files. If you import a non-C # code, it will not make any changes.

Wouldn't it be impossible to do this?
But I have written all the articles, there must be a way. After all, there is no serious way, but IO Dafa can't stand it.

Enough gossip, let's get started!
At this time, it is necessary to involve the AssetPostprocessor class just mentioned.
There is such a method, that is, when you import new resources, you must use the OnPreprocessAsset method.
That's easy to do, first upload the code:

using System.IO;
using UnityEditor;
using UnityEngine;

public class AssetPostManager : AssetPostprocessor
{
    
    
    void OnPreprocessAsset()
    {
    
    
        if (assetPath.StartsWith("Assets/Scene"))
        {
    
    
            CreateSceneSelectMenuFile();
        }
    }

    private void CreateSceneSelectMenuFile()
    {
    
    
        string fileStr = "using UnityEditor;\nusing UnityEngine;\nusing UnityEditor.SceneManagement;\n\npublic class SceneSelectMenu\n{
    
    {\n{0}}}";
        string[] sceneNames = Directory.GetFiles(Application.dataPath + "/Scene");
        string funcStr = "";
        string funcTemplateStr =
            "    [MenuItem(\"场景切换/打开{0}Scene\")]\n" +
            "    public static void Enter{0}Scene()\n" +
            "    {
    
    {\n" +
            "        if (Application.isPlaying) return;\n" +
            "        EditorSceneManager.OpenScene(\"Assets/Scene/{0}.unity\");\n" +
            "    }}\n\n";
        for (int index = 0; index < sceneNames.Length; index++)
        {
    
    
            string fileName = sceneNames[index].Substring(sceneNames[index].LastIndexOf("\\") + 1);
            if (fileName.EndsWith(".unity"))
            {
    
    
                string sceneName = fileName.Split('.')[0];
                funcStr += string.Format(funcTemplateStr, sceneName);
            }
        }
        fileStr = string.Format(fileStr, funcStr);

        StreamWriter writer = new StreamWriter(Application.dataPath + "/Script/Editor/DevTools/SceneSelectMenu.cs");
        writer.Write(fileStr);
        writer.Close();

        AssetDatabase.ImportAsset("Assets/Script", ImportAssetOptions.ImportRecursive | ImportAssetOptions.ForceSynchronousImport);
    }
}

It's also easy to understand, right?
My scenes are all placed in the Assets/Scene directory, so I only target the files placed in this directory.
First write the basic content needed for a file, fileStr. And a template for the MenuItem code block, funcTemplateStr.
Next, traverse the files in the scene directory. Well, all you need is the scene file name with the .unity suffix. Set these contents into fileStr.
Then use StreamWriter to write to the file. There are two things to keep in mind here: one is the oft-forgotten Close(). The other is, because this file is overwritten and written, it is best not to write other things into this file. (Don't ask me why I don't check if it doesn't exist before adding it, I'm lazy~)
Finally, remember to import and refresh the resources. Otherwise, you have to click the mouse outside of Unity and then click back, it will be very inky.

Take a look at the generated file:

using UnityEditor;
using UnityEngine;
using UnityEditor.SceneManagement;

public class SceneSelectMenu
{
    
    
    [MenuItem("场景切换/打开MainCityScene")]
    public static void EnterMainCityScene()
    {
    
    
        if (Application.isPlaying) return;
        EditorSceneManager.OpenScene("Assets/Scene/MainCity.unity");
    }

    [MenuItem("场景切换/打开MazeScene")]
    public static void EnterMazeScene()
    {
    
    
        if (Application.isPlaying) return;
        EditorSceneManager.OpenScene("Assets/Scene/Maze.unity");
    }

    [MenuItem("场景切换/打开StartScene")]
    public static void EnterStartScene()
    {
    
    
        if (Application.isPlaying) return;
        EditorSceneManager.OpenScene("Assets/Scene/Start.unity");
    }

}

Needle does not poke~

Oh yes, there are two things to say.
1. Only imported files will use the OnPreprocessAsset method, so operations such as deleting only one scene will not be performed. It can be processed through the method OnPostprocessAllAssets. (I'm lazy, so I didn't do it)
2. The scene name should not contain spaces. The name of the newly created scene is "New Scene" by default, and there may be an error report, but it doesn't matter, just continue to change it. (If it is not good to change it, then either modify it, the file with spaces will not be generated, or remove the spaces, or rewrite the method of creating Scene).

insert image description here

Guess you like

Origin blog.csdn.net/qql7267/article/details/109468864