今天可以说是有点成果了,可喜可贺~先上图
本节内容涉及到的类: EditorWindow, Physics, Handles, Camera, SceneView.
Editor类虽然可以使用OnSceneGUI来进行Scene视图里的各种定制操作,但是只能针对特定类型的脚本进行。如果想实现种怪这种编辑器常见需求,实现起来超级别扭。我尝试着基于Editor类来实现这个操作,发现除了在Inspector里锁住当前组件的视图外,没什么好方法了:创建一个空对象,放一个特定的类,实现一个特定的Editor,再每次编辑场景数据时手动锁定Inspector....想想都吐血了。
因此不可避免的寻求其他解决方案:EditorWindow
EditorWindowNamespace: UnityEditor
Parent class: ScriptableObject
Derive from this class to create an editor window.
关于EditorWindow的使用,U3D还是有一些基本例子的,今天我要谈的是关于SceneView的操作。
SceneView.onSceneGUIDelegate 该函数为定制提供了可能性,上代码先。
using UnityEngine; using UnityEditor; using System.Collections; using System.Text; public class SceneEditorWindow : EditorWindow { RaycastHit _hitInfo; SceneView.OnSceneFunc _delegate; static SceneEditorWindow _windowInstance; [MenuItem("Window/Scene Editor #`")] static void Init() { if(_windowInstance == null) { _windowInstance = EditorWindow.GetWindow(typeof(SceneEditorWindow)) as SceneEditorWindow; _windowInstance._delegate = new SceneView.OnSceneFunc(OnSceneFunc); SceneView.onSceneGUIDelegate += _windowInstance._delegate; } } void OnEnable() { } void OnDisable() { } void OnDestroy() { if (_delegate != null) { SceneView.onSceneGUIDelegate -= _delegate; } } void OnGUI() { } void OnInspectorGUI() { Debug.Log("OnInspectorGUI"); } static public void OnSceneFunc(SceneView sceneView) { _windowInstance.CustomSceneGUI(sceneView); } void CustomSceneGUI(SceneView sceneView) { Camera cameara = sceneView.camera; Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); if (Physics.Raycast(ray, out _hitInfo, 10000, -1)) { //Debug.DrawRay(ray.origin, ray.direction, Color.yellow); Vector3 origin = _hitInfo.point; origin.y += 100; if (Physics.Raycast(origin, Vector3.down, out _hitInfo)) { Handles.color = Color.yellow; Handles.DrawLine(_hitInfo.point, origin); float arrowSize = 1; Vector3 pos = _hitInfo.point; Quaternion quat; Handles.color = Color.green; quat = Quaternion.LookRotation(Vector3.up, Vector3.up); Handles.ArrowCap(0, pos, quat, arrowSize); Handles.color = Color.red; quat = Quaternion.LookRotation(Vector3.right, Vector3.up); Handles.ArrowCap(0, pos, quat, arrowSize); Handles.color = Color.blue; quat = Quaternion.LookRotation(Vector3.forward, Vector3.up); Handles.ArrowCap(0, pos, quat, arrowSize); //Handles.DrawLine(pos + new Vector3(0, 3, 0), pos); } } SceneView.RepaintAll(); } }
发现没啥可讲的了。。因为有之前GUILayout和Handles的知识后,其实只需要知道一个流程性的代码就行了。
而且EditorWindow的基本使用,U3D文档里已经有很充分的例子。
有一点需要注意,SceneView.RepaintAll(); 根据观察,SceneView在没有任何操作时,FPS估计是1,鼠标移动不会触发场景重绘,但是 onSceneGUIDelegate 确是一直在调用,所以加上这个之后,操作的反馈就变成实时的了,这会带来效率损耗---如果不影响操作的话,不用管。