您的位置:首页 > 移动开发 > Unity3D

Unity 编辑器扩展 Chapter2—Gizmos

2017-02-14 23:01 337 查看


二. 使用Gizoms绘制网格及矩阵转换使用

1. 创建Leve类,作为场景控制类:

1 using UnityEngine;
2 //使用namespace方便脚本管理
3 namespace RunAndJump {
4 //使用部分类partial将类依据不同的功能分布到各个文件中,便于功能区分个管理
5     public partial class Level : MonoBehaviour {
6         [SerializeField]
7         public int _totalTime = 60;
8         [SerializeField]
9         private float _gravity = -30;
10         [SerializeField]
11         private AudioClip _bgm;
12         [SerializeField]
13         private Sprite _background;
14
15         [SerializeField]
16         private int _totalColumns = 25;
17
18         [SerializeField]
19         private int _totalRows = 10;
20
21         public const float GridSize = 1.28f;
22
23         private readonly Color _normalColor = Color.grey;
24         private readonly Color _selectedColor = Color.yellow;
25         public int TotalTime {
26             get { return _totalTime; }
27             set { _totalTime = value; }
28         }
29
30         public float Gravity {
31             get { return _gravity; }
32             set { _gravity = value; }
33         }
34
35         public AudioClip Bgm {
36             get { return _bgm;}
37             set { _bgm = value; }
38         }
39
40         public Sprite Background {
41             get { return _background; }
42             set { _background = value; }
43         }
44
45         public int TotalColumns
46         {
47             get
48             {
49                 return _totalColumns;
50             }
51
52             set
53             {
54                 _totalColumns = value;
55             }
56         }
57
58         public int TotalRows
59         {
60             get
61             {
62                 return _totalRows;
63             }
64
65             set
66             {
67                 _totalRows = value;
68             }
69         }
70
71     //绘制边界
72         private void GridFrameGizmo(int cols, int rows)
73         {
74             Gizmos.DrawLine(new Vector3(0,0,0),new Vector3(0,rows*GridSize,0) );
75             Gizmos.DrawLine(new Vector3(0, 0, 0), new Vector3(cols*GridSize,0, 0));
76             Gizmos.DrawLine(new Vector3(cols*GridSize, 0, 0), new Vector3(cols*GridSize, rows * GridSize, 0));
77             Gizmos.DrawLine(new Vector3(0, rows*GridSize, 0), new Vector3(cols*GridSize, rows * GridSize, 0));
78         }
79
80 //绘制内部线条
81         private void GridGizmos(int cols, int rows)
82         {
83             for (int i = 0; i < cols; i++)
84             {
85                 Gizmos.DrawLine(new Vector3(i*GridSize,0,0),new Vector3(i*GridSize,rows*GridSize,0) );
86             }
87
88             for (int j = 0; j < rows; j++)
89             {
90                 Gizmos.DrawLine(new Vector3(0,j * GridSize, 0), new Vector3(cols * GridSize, j * GridSize, 0));
91             }
92         }
93
94     //D使用unity默认的OnDrawGizmos方法来绘制Gzimos
95         private void OnDrawGizmos()
96         {
97             Color oldColor = Gizmos.color;//修改的这些属性都是静态属性,所以要在修改前保存其值,修改后再复原,防止后续使用该静态属性是修改后的
98             Matrix4x4 oldMatrix = Gizmos.matrix;//修改的这些属性都是静态属性,所以要在修改前保存其值,修改后再复原,防止后续使用该静态属性是修改后的
99             Gizmos.matrix = transform.localToWorldMatrix;//该语句可以为gizmos提供该transform位移,旋转,缩放等特性
100
101             Gizmos.color = _normalColor;
102             GridGizmos(_totalColumns,_totalRows);
103             GridFrameGizmo(_totalColumns,_totalRows);
104
105             Gizmos.color = oldColor;//恢复修改后的静态属性
106             Gizmos.matrix = oldMatrix;//恢复修改后的静态属性
107         }
108
109         private void OnDrawGizmosSelected()
110         {
111             Color oldColor = Gizmos.color;
112             Matrix4x4 oldMatrix = Gizmos.matrix;
113             Gizmos.matrix = transform.localToWorldMatrix;
114
115
116             Gizmos.color = _selectedColor;
117             GridFrameGizmo(_totalColumns, _totalRows);
118
119             Gizmos.color = oldColor;
120             Gizmos.matrix = oldMatrix;
121
122         }
123
124         /// <summary>
125         /// 将世界坐标转换为grid网格中的点坐标
126         /// </summary>
127         /// <param name="point">世界坐标</param>
128         /// <returns></returns>
129         public Vector3 WordToGridCoordinates(Vector3 point)
130         {
131             Vector3 gridPoint=new Vector3((int)((point.x-transform.position.x)/GridSize),(int)((point.y-transform.position.y)/GridSize),0.0f);
132             return gridPoint;
133         }
134
135         /// <summary>
136         /// Grid网格中的位置转换为世界坐标坐标
137         /// </summary>
138         /// <param name="col">行值</param>
139         /// <param name="row">列值</param>
140         /// <returns></returns>
141         public Vector3 GridToWordCoordinates(int col,int row)
142         {
143             Vector3 wordPoint=new Vector3(transform.position.x+(col*GridSize/2.0f),transform.position.y+(row*GridSize/2.0f),0.0f);
144             return wordPoint;
145         }
146         /// <summary>
147         /// 坐标位置是否在网格边界内
148         /// </summary>
149         /// <param name="point"></param>
150         /// <returns></returns>
151         public bool IsInsideGridBounds(Vector3 point)
152         {
153             float minX = transform.position.x;
154             float maxX = minX + _totalColumns*GridSize;
155             float minY = transform.position.y;
156             float maxY = minY + _totalRows*GridSize;
157             return (point.x >= minX && point.x <= maxX && point.y >= minY && point.y <= maxY);
158         }
159
160         /// <summary>
161             /// 坐标位置是否在网格边界内
162             /// </summary>
163             /// <param name="point"></param>
164             /// <returns></returns>
165
166         public bool IsInsideGridBounds(int col,int row)
167         {
168             return (col>=0&&col<_totalColumns&&row>=0&&row<=_totalRows);
169         }
170     }
171 }


2. 创建EditorUtil类,作为辅助工具类:

1 using UnityEngine;
2 using System.Collections;
3 using UnityEditor;
4 using UnityEditor.SceneManagement;
5
6 namespace RunAndJump.LevelCreator  //为防止类名冲突,使用namespace时一个好的解决方案
7 {
8     public class EditorUtil
9     {
10
11         //创建新场景
12         public static void NewScene()
13         {
14             //该方法后续过时,被下面方法替代:EditorApplication.SaveCurrentSceneIfUserWantsTo();
15             EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();//当前场景有未保存的东西是,弹出对话框提醒是否保存当前场景
16             //该方法后续过时,被下面方法替代:EditorApplication.NewScene();
17             EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
18         }
19
20
21         //清空场景
22         public static void CleanScene()
23         {
24             GameObject[] allObjects = Object.FindObjectsOfType<GameObject>();
25
26             foreach (GameObject go in allObjects)
27             {
28                 GameObject.DestroyImmediate(go);
29             }
30         }
31
32         //创建新关卡
33         public static void NewLevel()
34         {
35             NewScene();
36             CleanScene();
37
38             //可以在创建新关卡时添加上必要的游戏对象
39             //add something...
40
41             GameObject levelGo = new GameObject("Level");
42             levelGo.transform.position=Vector3.zero;
43             levelGo.AddComponent<Level>();
44
45         }
46     }
47 }


3. 创建MenuItems类,作为编辑器菜单工具类:

1 using UnityEngine;
2 using System.Collections;
3 using UnityEditor;
4
5 namespace RunAndJump.LevelCreator
6 {
7
8     //菜单项管理类,用来控制扩展方法在菜单项中显示
9     public class MenuItems
10     {
11         [MenuItem("Tools/LevelCreator/NewLevelScene %q") ]
12         private static void NewLevel()
13         {
14             EditorUtil.NewLevel();
15         }
16     }
17 }


4. 创建SnapToGridTest类,用来测试Leve类中方法:

1 using UnityEngine;
2 using System.Collections;
3 using RunAndJump;
4
5 [ExecuteInEditMode]//在editor场景模式下不用运行就调用
6 public class SnapToGridTest : MonoBehaviour {
7
8     // Update is called once per frame
9     void Update ()
10     {
11         print(name+" in level");
12         Vector3 gridCoord = Level.Instance.WordToGridCoordinates(transform.position);
13         transform.position = Level.Instance.GridToWordCoordinates((int) gridCoord.x, (int) gridCoord.y);
14     }
15
16     private void OnDrawGizmos()
17     {
18         print("gizoms");
19         Color oldColor = Gizmos.color;
20         Gizmos.color = (Level.Instance.IsInsideGridBounds(transform.position)) ? Color.green : Color.red;
21         Gizmos.DrawCube(transform.position,Vector3.one*Level.GridSize);
22         Gizmos.color = oldColor;
23     }
24 }


效果:

我们通过MenuItems创建的菜单调用EditorUtil中创建场景的方法,场景中在OnDrawGizoms方法中绘制出自己的网格。现在创建一个空物体为其绑上SnapToGridTest脚本用来验证level中用来对齐坐标到网格和验证是否出界的方法。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: