Unity3d Editor Easy Tutorial

Source: Internet
Author: User
Tags arrays
"Turn from" http://blog.csdn.net/lilanfei/article/details/7680802 Unity3d Editor Easy tutorialCategory: Unity3d 2012-06-20 19:23 2711 people Read reviews (0) Favorite reports

Directory (?)   [+] Star Custom Editor Easy tutorial An introduction to Custom editors original address http://catlikecoding.com/unity/tutorials/star/ introduction Introduction

This tutorial will let you learn how to create a Star control and how to make a custom editor for the control. You will learn to: dynamically build mesh. Use a nested class. Create a custom editor. Use Serializedobject. Support what you see is what you gain. Provides support for Undo, Redo, Reset, and prefab. Supports multi-object editing. Supports editing in Scene view.

Let's assume that you've learned the basics of Unity C # and the Fundamentals of the Unity editor. If you have completed the relevant study, let ' s go! Establish Star class Creating the star

We built a new unity project and then built a new C # script to name it star. We're going to use this script to create a triangle-paneled star that needs a mesh. what is mesh.

The 3D model is made of polygonal stitching, a complex polygon that is actually stitched together by multiple triangular faces. So the surface of a 3D model is made up of a plurality of triangular faces connected to each other. In three-dimensional space, the set of points that make up these triangular faces and the edges of the triangles is mesh.

<span class= "Mark" >using unityengine;</span>

<span class= "Mark" >public class Star: Monobehaviour {</span>

	<span class= "Mark" >private Mesh mesh;</span>

<span class= "Mark" >}</span>

Any use of the mesh must be paired with a meshfilter component, and Meshfilter is used for the Meshrenderer component. Only in this way can it be drawn by unity. Therefore, these components must be loaded onto the Gameobject object, and our star object must do the same.

Of course, we can add these components manually, but the default auto-add is a better approach. So we need to add a requirecomponent class as a feature of the Star object. What is the attribute of a class.

Attributes attach a label to the class to tell the compiler what to do with the class. is an additional description of the class, in addition to the code for the class declaration. In addition, attributes are not only for classes, but also for methods and properties. What is the use of typeof.

TypeOf is an operator that can obtain the type description data of any class, and the name of the class is most commonly used in the data. Then why not just write the name of the class directly in the code? Because all assignments and operations in the code require variables, using the name of the class directly results in a compilation error.

Using Unityengine;

<span class= "Mark" >[requirecomponent (typeof (Meshfilter), typeof (Meshrenderer))]</span> public
Class Star:monobehaviour {

	private mesh mesh;

}

Now, let's create a new empty gameobject, name it my first star, and then drag our script Star to my first star. You can see that My first star has two components, Meshrenderer and star. Drag one to get three

The next step is to create a mesh. We need to do this in Unity's start event, and the start event will occur when the program starts. We also need to give this new mesh a name in Meshfilter.

Using Unityengine;

[Requirecomponent (typeof (Meshfilter), typeof (Meshrenderer))]
public class Star:monobehaviour {

	private mesh mesh;

	<span class= "Mark" >void Start () {</span>
		<span class= "Mark" >GetComponent<MeshFilter> () . Mesh = Mesh = new Mesh ();</span>
		<span class= "mark" >mesh.name = "Star mesh";</span>
	<span Class= "Mark" >}</span>
}
No editor mode and live Preview mode

Of course, now we don't see anything in preview mode, because the mesh is still empty. So let's start editing the vertex array, our Star class needs a property to set the number of vertices, and the relative distance between those points and the center.

The first vertex is the center point of the star, and the rest of the vertices are arranged clockwise. We will use a four-dollar number to calculate the arrangement of these points. Because we assume that the z-axis is looked down, the rotation angle is negative, otherwise the points are arranged counterclockwise. We don't need to set the first point because vectors are set to 0 by default, and the local coordinate system is used in the mesh.

Using Unityengine; [Requirecomponent (typeof (Meshfilter), typeof (Meshrenderer))] public class Star:monobehaviour {<span class= "Mark" & 

	Gt;public Vector3 point = vector3.up;</span> <span class= "Mark" >public int numberofpoints = 10;</span>
	private mesh mesh; <span class= "Mark" >private vector3[] vertices;</span> void Start () {getcomponent<meshfilter> (). Mes
		h = mesh = new mesh ();

		Mesh.name = "Star Mesh";  <span class= "Mark" >vertices = new Vector3[numberofpoints + 1];</span> <span class= "Mark" >float angle = <span style= "Color:white; Background-color:rgb (0, 70, 153); " >-</span>360f/numberOfPoints;</span> <span class= "Mark" >for (int v = 1; v < vertices. Length; v++) {</span> <span class= "Mark" >vertices[v] = Quaternion.euler (0f, 0f, Angle * (v <span style= "Color:wh Ite Background-color:rgb (0, 70, 153); " >-</span> 1) * point;</span> <span class= "Mark" &Gt;} </span> <span class= "Mark" >mesh.vertices = vertices;</span>}}
New editor Properties

The triangular faces are saved as a vertex array, with three vertices per polygon. Because we use triangles to describe polygons, each triangle starts at the same midpoint and is connected to the other triangles. The last triangle is connected to the first triangle. For example, if there are four triangles, then the vertex arrays are {0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 1}.

Using Unityengine; [Requirecomponent (typeof (Meshfilter), typeof (Meshrenderer))] public class Star:monobehaviour {public Vector3 point =
	Vector3.up;

	public int numberofpoints = 10;
	private mesh mesh;
	Private vector3[] vertices;  <span class= "Mark" >private int[] triangles;</span> void Start () {getcomponent<meshfilter> (). Mesh =
		mesh = new mesh ();

		Mesh.name = "Star Mesh";
		vertices = new vector3[numberofpoints + 1]; <span class= "Mark" >triangles = new int[numberofpoints * 3];</span> float angle = <span style= "Color:whit E Background-color:rgb (0, 70, 153); "
		>-</span>360f/numberOfPoints; for (int v = 1<span class= "Mark", T = 1</span>; v < vertices. Length; V++<span class= "Mark", t + = 3</span>) {Vertices[v] = Quaternion.euler (0f, 0f, Angle * (v <span style= "c Olor:white; Background-color:rgb (0, 70, 153); "
			>-</span> 1)) * point; <span class= "Mark" >triangles[t] = v;</span&Gt <span class= "Mark" >triangles[t + 1] = v + 1;</span>} <span class= "Mark" >triangles[triangles. Length <span style= "color:white; Background-color:rgb (0, 70, 153); "
		>-</span> 1] = 1;</span> mesh.vertices = vertices; <span class= "Mark" >mesh.triangles = triangles;</span>}}
A simple star.

Now, our star looks like just a simple polygon. Unity also prompts for the loss of material coordinates, because the default shader requires these coordinates. We will not use a texture to depict all the stars, let us eliminate this warning by building our own shader, this shader will only use vertex coloring.

We set up a new shader to name it star, and then write the following code. what is Cgprogram.

Basically, data flows from the Unity engine into the graphics card, where it ' s processed per vertex. Then interpolated data flows from the vertices down to the individual pixels. We pass position and color data all the. The only additional thing we are convert vertex positions from World space to screen space.
The statements above the Cgprogram switch off default lighting and depth buffer writing. Culling is switched off so we can see the triangles from both sides, not just the front. "Blend Srcalpha oneminussrcalpha" is the default alpha blending, allowing for transparency. Why not use fixed-function shader.

Fixed-function shader already belongs to outdated technology. Cgprogram has more powerful capabilities in turning data into screen pixels.

Shader "Star" {
	subshader{
		tags{"Queue" = "Transparent" "ignoreprojector" = "True" "rendertype" = "Transparent"}
		Blend Srcalpha Oneminussrcalpha
		Cull off
		Lighting off
		zwrite off
		pass{
			cgprogram
				#pragma vertex vert
				#pragma fragment Frag

				struct Data {
					float4 vertex:position;
					Fixed4 color:color;
				};

				Data vert (data v) {
					V.vertex = Mul (UNITY_MATRIX_MVP, V.vertex);
					return v;
				}

				FIXED4 Frag (data f): COLOR {
					return f.color;
				}
			ENDCG
		}}}

Now we create a new material ball, named star, set the shader to the star we just wrote and give the material ball to my first star. After adding a material ball

Vertex coloring is white by default, so our polygons now turn white. We want a more beautiful star. So let's define a color for each point.

Let's add another frequency property so we can have the program automatically repeat the sequence of points without having to define all the points individually. This option replaces the numberofpoints.

At the end we need to confirm that the frequency property is correct and that the star has at least one point. If not, our code might go wrong. Why check both for null and the length?

When freshly created, our star component won ' t has an array yet. It's also technically possible for scripts and explicitly set our arrays to null later on. We need to watch out for the, to prevent errors. Only if the array does exists does we go ahead and check its length as well.

Using Unityengine; [Requirecomponent (typeof (Meshfilter), typeof (Meshrenderer))] public class Star:monobehaviour {<span class= "Mark" & Gt;public vector3[] points;</span> <span class= "mark" >public int frequency = 1;</span> private Mesh m
	Esh
	Private vector3[] vertices;

	Private int[] triangles;
		void Start () {getcomponent<meshfilter> (). Mesh = Mesh = new mesh ();

		Mesh.name = "Star Mesh"; <span class= "Mark" >if (Frequency < 1) {</span> <span class= "Mark" >frequency = 1;</span> < Span class= "Mark" >}</span> <span class= "Mark" >if (points = = NULL | | points. Length = = 0) {</span> <span class= "Mark" >points = new vector3[]{vector3.up};</span> <span class= "Mark" >}</span> <span class= "Mark" >int numberofpoints = frequency * points.
		length;</span> vertices = new vector3[numberofpoints + 1];
		Triangles = new int[numberofpoints * 3]; float angle = <span style= "Color:white; Background-color:rgb (0, 70, 153); "
		>-</span>360f/numberOfPoints; for (int <span class= "mark" >if = 0,</span> v = 1, t = 1<span class= "Mark" >; IF < frequency; if++) {< /SPAN> <span class= "Mark" >for (int ip = 0; IP < points. Length;  IP + = 1,</span> V + = 1, t + = 3) {Vertices[v] = Quaternion.euler (0f, 0f, Angle * (v <span style= "color:white; Background-color:rgb (0, 70, 153); "
				>-</span> 1) * <span class= "Mark" >points[iP]</span>;
				Triangles[t] = v;
			Triangles[t + 1] = v + 1; <span class= "Mark" >}</span>} triangles[triangles. Length <span style= "color:white; Background-color:rgb (0, 70, 153); "

		>-</span> 1] = 1;
		Mesh.vertices = vertices;
	Mesh.triangles = triangles; }
}
Well-configured points

We need some color. It's easy to specify the same color for all the vertices, but it's boring. Let's try assigning a color to each vertex. We need an array to hold these color data, and we must keep the number of colors and vertices consistent. This is a little bit of a hassle, let's just replace it with another way to create a new class in the Star class that holds the color and position of a vertex. Then we can use the array of this class instead of the vector array.

This type of point, if used outside of the Star class, is star.point. Within star, point is available. To allow unity to serialize the point, we add the system.serializable attribute to point. Why not structure?

Because Star.point is so lightweight and its data are always needed all at once, it would make sense to use a struct Typ E and avoid the overhead that objects Add. However, Unity does not serialization of custom struct types. So your ' re stuck using classes to bundle data from want to store.
If You ' re really concerned on the object overhead and possible null errors, you can always store the offset and co Lor data in separate arrays. However, then you would need-make sure, the these arrays always stay synchronized. While this is definitely doable, the class approach is simpler. That's why I use it in this tutorial.

<span class= "Mark" >using system;</span> using Unityengine; [Requirecomponent (typeof (Meshfilter), typeof (Meshrenderer))] public class Star:monobehaviour {<span class= "Mark" & Gt [serializable]</span> <span class= "Mark" >public class point {</span> <span class= "Mark" > Public Color color;</span> <span class= "Mark" >public Vector3 offset;</span> <span class= "Mark" ;}
	</span> public <span class= "Mark" >point</span>[] points;

	public int frequency = 1;
	private mesh mesh;
	Private vector3[] vertices;

	<span class= "Mark" >private color[] colors;</span> private int[] triangles;
		void Start () {getcomponent<meshfilter> (). Mesh = Mesh = new mesh ();

		Mesh.name = "Star Mesh";
		if (Frequency < 1) {frequency = 1; } if (points = = NULL | | points. Length = = 0) {points = new <span class= "Mark" >point</span>[]{<span class= "Mark" >new Point () </span
		>}; } intnumberofpoints = frequency * points.
		Length;
		vertices = new vector3[numberofpoints + 1];
		<span class= "Mark" >colors = new Color[numberofpoints + 1];</span> triangles = new int[numberofpoints * 3]; float angle = <span style= "Color:white; Background-color:rgb (0, 70, 153); "
		>-</span>360f/numberOfPoints; for (int iF = 0, v = 1, t = 1; iF < frequency; if++) {for (int ip = 0; IP < points. Length; IP + = 1, v + = 1, t + = 3) {Vertices[v] = Quaternion.euler (0f, 0f, Angle * (v <span style= "color:white; background-c Olor:rgb (0, 70, 153); "
				>-</span> 1) * Points[ip]<span class= "Mark" >.offset</span>;
				<span class= "Mark" >colors[v] = points[ip].color;</span> triangles[t] = v;
			Triangles[t + 1] = v + 1; }} triangles[triangles. Length <span style= "color:white; Background-color:rgb (0, 70, 153); "

		>-</span> 1] = 1;
		Mesh.vertices = vertices; <span class= "Mark" >mesh.colors = Colors;</span> mesh.triangles = triangles; }
}
After having the color

Finally, it's about the center point. Now, we haven't set a color for it, so it's always transparent. Let's add a color attribute to it, and eventually the star looks beautiful.

Using System;

Using Unityengine; [Requirecomponent (typeof (Meshfilter), typeof (Meshrenderer))] public class Star:monobehaviour {[Serializable] public
		Class Point {public color color;
	public Vector3 offset;
	} public point[] points;
	public int frequency = 1;
	<span class= "Mark" >public Color centercolor;</span> private mesh mesh;
	Private vector3[] vertices;
	Private color[] colors;

	Private int[] triangles;
		void Start () {getcomponent<meshfilter> (). Mesh = Mesh = new mesh ();

		Mesh.name = "Star Mesh";
		if (Frequency < 1) {frequency = 1; } if (points = = NULL | | points.
		Length = = 0) {points = new point[]{new Point ()}; } int numberofpoints = frequency * points.
		Length;
		vertices = new vector3[numberofpoints + 1];
		colors = new Color[numberofpoints + 1];
		Triangles = new int[numberofpoints * 3]; float angle = <span style= "Color:white; Background-color:rgb (0, 70, 153); "
		>-</span>360f/numberOfPoints; <span class= "Mark ">colors[0" = centercolor;</span> for (int iF = 0, v = 1, t = 1; iF < frequency; if++) {for (int iP = 0 ; IP < points. Length; IP + = 1, v + = 1, t + = 3) {Vertices[v] = Quaternion.euler (0f, 0f, Angle * (v <span style= "color:white; background-c Olor:rgb (0, 70, 153); "
				>-</span> 1) * POINTS[IP].OFFSET;
				COLORS[V] = Points[ip].color;
				Triangles[t] = v;
			Triangles[t + 1] = v + 1; }} triangles[triangles. Length <span style= "color:white; Background-color:rgb (0, 70, 153); "

		>-</span> 1] = 1;
		Mesh.vertices = vertices;
		Mesh.colors = colors;
	Mesh.triangles = triangles; }
}
Beautiful stars, trouble with the editor Build Editor Creating the Inspector

Star looks good now, but it's a little cumbersome to design. The default editor has a bit of an egg ache, let's make one ourselves.

The code for all editor classes needs to be placed in the editor folder, so unity can correctly identify the code. Editor's name on the line, where it doesn't matter. We are now building the editor under the root directory, which is assets. Then build a Starinspector class code file, put it in the editor. type of editor?

It is necessary to understand that there is not only one type of editor panel. In this example, we use the Properties panel--inspector, the rest of the editorwindow--Edit dialog box, you can implement a fully customizable pop-up dialog box, as well as the scriptablewizard--Wizard dialog box, and the editor menu.

Directory structure

Because our class is an editor class, it needs to inherit the editor class instead of Monobehaviour. We also need to add a property to tell unity that this class is defining the editor for the Star class.

<span class= "Mark" >using unityeditor;</span>
<span class= "Mark" >using Unityengine;</span >

<span class= "Mark" >[customeditor (typeof (Star))]</span>
<span class= "Mark" >public Class Starinspector:editor {}</span>

So far, we haven't changed the star's editor. We need to replace the default editor. We can do this by overloading the Oninspectorgui event of the editor class.

Using Unityeditor;
Using Unityengine;

[Customeditor (typeof (Star))]
public class Starinspector:editor {

	<span class= "Mark" >public override void Oninspectorgui () {}</span>
}
An empty editor

The default editor pinch. It's gone.

Because we didn't write any code in the Oninspectorgui event, everything was blank. The Drawdefaultinspector method can be used to draw the default editor interface, but we do not want this, or try something else.

We will first confirm which star object is selected and should be displayed in the editor. We can use the target property to represent this object, the target property is a property of editor, we inherit the editor, so we also inherit this property, it is very convenient to use it directly. While this is not necessary, we can use Serializedobject to wrap the target, which is handy because it makes it easy to support many editors, such as undo.

We used the Serializedobject to extract its data through the Serializedproperty object. We're going to initialize all of the Star class variables in the Onenable event. This event occurs when a gameobject that adds a star component is selected. What ' s a serializedobject?

Serializedobject is a class this acts as a wrapper or proxy for Unity objects. You can use it for extract data from the object even if you don't have a clue-what ' s inside it. This is what the Unity inspector can show default inspectors for anything you create yourself. As a bonus, you get the undo support for free.

using unityeditor; using Unityengine; [Customeditor (typeof (Star))] public class Starinspector:editor {<span class= "mark" >private serializedobject STA r;</span> <span class= "Mark" >private serializedproperty</span> <span class= "Mark" >points, </span> <span class= "Mark" >frequency,</span> <span class= "Mark" >centerColor;</span> & Lt;span class= "Mark" >void onenable () {</span> <span class= "Mark" >star = new Serializedobject (target); &L t;/span> <span class= "Mark" >points = Star. Findproperty ("points");</span> <span class= "Mark" >frequency = Star. Findproperty ("Frequency");</span> <span class= "Mark" >centercolor = Star. Findproperty ("Centercolor");</span> <span class= "Mark" >}</span> public override void Oninspectorgui () {}} 

Every time the editor is updated, we need to make sure that Serializedobject is updated in real time. That's the first thing we're going to do in the Oninspectorgui event. We can then simply call Editorguilayout.propertyfield to display our properties, displaying all the elements of points and its interior. After that we end all property modifications and apply to the selected component. What ' s editorguilayout?

Editorguilayout is a utility class for displaying stuff in the Unity editor. It contains methods for drawing all kinds of things, in this case we ' re simply using the default method for drawing a Seri Alizedproperty.
There's also an Editorgui utility class which does the same thing, but requires your to perform your own GUI layout.

Using Unityeditor;
Using Unityengi

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.