今天可以说是有点成果了,可喜可贺~先上图
本节内容涉及到的类: 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 确是一直在调用,所以加上这个之后,操作的反馈就变成实时的了,这会带来效率损耗---如果不影响操作的话,不用管。