分享

Unity 编辑器扩展 Chapter2

 kiki的号 2017-04-22


 


二. 使用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中用来对齐坐标到网格和验证是否出界的方法。



 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多