📜 ⬆️ ⬇️

Scripts for the editor in Unity3D

Today we will talk about how to write scripts for Unity Editor. The article is intended for those who are already familiar with Unity3D, managed to do something, but had not yet decided to try writing scripts for the editor.

In short, in the editor mode, scripts can do absolutely everything the same as in the game mode.

Let's start with the simple. Suppose we want to create 10 cubes in editorial mode and arrange them in a line. First, let's simplify the task and forget about the editor, let's make these cubes be created when the application starts.

public class CreateCubes : MonoBehaviour { // Use this for initialization void Start () { Create10Cubes(); } private void Create10Cubes() { Vector3 position = new Vector3(0, 0, 0); for (int i = 0; i < 10; i++) { GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); cube.transform.position = position; position += new Vector3(5, 0, 0); } } } 

')
Now we will try to execute this code in editor mode. To do this, add just one magic attribute [ContextMenu ()] to the Create10Cubes () function:

so that the code looks like this:
 [ContextMenu("CreateCubes")] private void Create10Cubes() { Vector3 position = new Vector3(0, 0, 0); for (int i = 0; i < 10; i++) { GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); cube.transform.position = position; position += new Vector3(5, 0, 0); } } 




Now, if we right-click on the script header, the CreateCubes item will appear there, when clicked, the function will also be executed exactly.

Important note: the function marked with the ContextMenu attribute should not have parameters, or rather, if it has parameters, you cannot call it this way.

Personally, I use this method when you need to do something with a group of objects, for example, to turn off the casting of shadows for all children of an object who have “withoutshadow” in the name:

 [ContextMenu("DisableCastShadows")] private void DisabeCastShadows() { Renderer[] renderers = GetComponentsInChildren<Renderer>() .Where(x => x.name.Contains("withoutshadow")) .ToArray(); foreach (var r in renderers) { r.castShadows = false; } } 

In general, the method is good for one-time actions on a bunch of objects - quickly threw the necessary code in a separate class, threw it on the desired object and immediately removed this class to the edren fen.

Now let's solve the following problem: we want to bake occlusion culling. To do this, we need to tick Occluder Static with all objects that block other objects, and with Occludee Static tick all that will be hidden behind Occluder `s. That is, we need to isolate all static objects, put both daws (actually everything) to opaque scopes, only Occludee should be transparent, and Occluder to turn off.

It would seem, well, such a thing, ran around the scene with handles - put up someone who needs ticks - that's all. But the problem is that there can be a lot of objects in the scene and in the course of the project development the scene is likely to change. Watch yourself for all these checkmarks - you can go crazy. Therefore, we will write a little scriptic that does it for us.

To begin with, we will write a useful code that does our work, and then we arrange it into a separate wizard:



There are two tasks here:

1) Find objects of interest to us in the scene;
2) Place the necessary checkboxes.

Let's make the code in the form of a separate command, so that it can be called from any place and it does not depend on which wizard you call it. Attention: the file containing the following code must be placed in a folder called Editor, this is necessary so that this code does not fall into the main build:

 using UnityEngine; using UnityEditor; using System.Linq; public class SetStaticOclluderFlagsCmd { private const int TransparentQueue = 3000; const int OverlayQueue = 4000; public void Execute() { var scene =Object.FindObjectsOfType(typeof(GameObject)); var transparents = scene.Where(o =>IsStatic(o) && IsTransparent(o)).ToArray(); var occluders = scene.Where(o => IsStatic(o) && !IsTransparent(o)).ToArray(); SceneModeUtility.SetStaticFlags(transparents, (int)StaticEditorFlags.OccluderStatic, false); SceneModeUtility.SetStaticFlags(transparents, (int)StaticEditorFlags.OccludeeStatic, true); SceneModeUtility.SetStaticFlags(occluders, (int)StaticEditorFlags.OccluderStatic, true); SceneModeUtility.SetStaticFlags(occluders, (int)StaticEditorFlags.OccludeeStatic, true); Debug.Log("SetStaticOclluderFlagsCmd done"); } private bool IsStatic(Object obj) { GameObject gameObject = obj as GameObject; if (gameObject == null) return false; return GameObjectUtility.AreStaticEditorFlagsSet(gameObject, StaticEditorFlags.BatchingStatic); } private bool IsTransparent(Object obj) { GameObject gameObject = obj as GameObject; if (gameObject == null ||gameObject.renderer == null) return false; return obj.renderer.sharedMaterials.Any(x => x.renderQueue >= TransparentQueue && x.renderQueue < OverlayQueue);; } } 


Here we assume that static objects have already been somehow found (most likely with pens) and ticked them with a Static, which means including BatchingStatic.

Regarding the implementation of the IsTransparent () method.
I am not good at writing shaders and I cannot guarantee that such an implementation is correct, I can only say that it works on standard shaders. If someone tells you a more correct way of implementation, I will definitely replace him.


Now let's create a separate wizard so that you can conveniently call this command:

This is where the EditorWindow class comes in handy.

 using UnityEngine; using UnityEditor; public class OcclusionCullingUtilites : EditorWindow { [MenuItem("Window/OcclusionCullingUtilites")] static void Init() { GetWindow<OcclusionCullingUtilites>(); } void OnGUI() { if(GUILayout.Button("SetStaticFlags")) { SetStaticOclluderFlagsCmd cmd = new SetStaticOclluderFlagsCmd(); cmd.Execute(); } } } 


On this, while we finish our review, it turned out far from complete.

In the following articles, I plan to describe how to create custom inspectors for your classes, how to interfere with the process of importing assets, how to bake shadows at 20 levels in turn and get screenshots of the result to your email.

Source: https://habr.com/ru/post/236451/


All Articles