[Unity]自定义地图编辑器(Scene视图下,EditorWindow的简单应用)
最近的游戏又很多关卡需要配置(XML保存),给策划写了个非常简单的编辑器,记录下+废话下
1:Editor下打开新窗口需要继承EditorWindow,然后使用获取窗口即可,注意放在Editor文件夹下
1 public class DrawGameLevel : EditorWindow 2 { 3 [MenuItem("Maps/Creater %M")]//后面快捷键 4 public static void OpenMapCreate() 5 { 6 DrawGameLevel window = EditorWindow.GetWindow<DrawGameLevel>("地图编辑器"); 7 window.Show(); 8 window.minSize = new Vector2(400, 800);//设置最大和最小 9 window.maxSize = new Vector2(400, 1200); 10 } 11 }
2:因为是在Scene视图下进行操作,所以注册SceneView.duringSceneGui事件,在OnEnable中
1 void OnEnable() 2 { 3 SceneView.duringSceneGui += OnSceneGUI; 4 //初始化一些东西 5 } 6 7 void OnDestroy() 8 { 9 SceneView.duringSceneGui -= OnSceneGUI; 10 }
3:接着编写OnSceneGUI,这里首先会替换掉Scene视图以前的响应事件(就是说在Scene中点击预制体不再会选择它了),然后发射射线检测要绘制的地图,射线是必须要有碰撞体的,所以在场景中预先准备一个Plane,正对着屏幕,只有射线碰撞到了Plane才会进行绘制
1 private bool _drag = false; 2 void OnSceneGUI(SceneView sceneView) 3 { 4 HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));//为scene响应添加默认事件,用来屏蔽以前的点击选中物体 5 if (Event.current.type == EventType.MouseDown && Event.current.button == 0)//点击 6 { 7 } 8 else if (Event.current.type == EventType.MouseUp && Event.current.button == 0)//抬起 9 { 10 if (!_drag) 11 { 12 OnMouseEvent(); 13 } 14 15 _drag = false; 16 } 17 else if (Event.current.type == EventType.MouseDrag && Event.current.button == 0)//拖动 18 { 19 OnMouseEvent(); 20 _drag = true; 21 } 22 } 23 24 private void OnMouseEvent() 25 { 26 Vector2 mousePos = Event.current.mousePosition;//获取鼠标坐标 27 mousePos.y = Camera.current.pixelHeight - mousePos.y;//这里的鼠标原点在左上,而屏幕空间原点左下,翻转它 28 //mousePos.y = (float)Screen.height - mousePos.y - 40f;这种写法也成 29 Ray ray = Camera.current.ScreenPointToRay(mousePos); 30 RaycastHit rh; 31 if (Physics.Raycast(ray, out rh, 3000f)) 32 { 33 //判断是否射到了plane,是的话进行操作便是 34 } 35 }
4:Scene视图的处理结束,接着继续绘制EditorWindow,在OnGUI中绘制
1 string maxRow = String.Empty; 2 string maxCol = string.Empty; 3 private int _select = 0; 4 private Texture[] _items = new Texture[12]; 5 void OnGUI() 6 { 7 maxRow = EditorGUILayout.TextField("Row(最大行数)", maxRow); 8 maxCol = EditorGUILayout.TextField("Col(最大列数)", maxCol); 9 if (GUILayout.Button("开始绘画")) 10 { 11 //按钮操作 12 } 13 if (GUILayout.Button("尝试读取关卡")) 14 { 15 EditorUtility.DisplayDialog("读取失败", "配置文件不存在或者关卡不存在\n读取失败,尝试读取关卡为:" + _levelNum + "\n请检查配置文件", "好的");//这个方法可以弹出确认框,返回bool 16 } 17 EditorGUILayout.BeginHorizontal("box"); 18 int sizeY = 100 * Mathf.CeilToInt(_items.Length / 4f); 19 _select = GUI.SelectionGrid(new Rect(new Vector2(0, 155), new Vector2(100 * 4, sizeY)), _select, _items, 4);//可以给出grid选择框,需要传入贴图数组_items 20 }
5:已经结束了,怎么绘制上去的?OnMouseEvent()中发现点击到了,AssetDataBase.Load生成prefab上去就行,而传入Grid中的Texture,可以使用AssetPreview.GetAssetPreview(AssetDatabase.LoadAssetAtPath<Object>("path.png")) as Texture;来获取到预览图
最后保存可以自己写正反解析xml,也可以直接把场景内绘制好的拖成预制体
主要关注的就是 阻止Scene事件,Scene射线,获取预览
以上~废话结束