Unity3D 场景编辑器扩展学习笔记-EditorWindow

今天可以说是有点成果了,可喜可贺~先上图

Unity3D 场景编辑器扩展学习笔记-EditorWindow_第1张图片


本节内容涉及到的类: EditorWindow, Physics, Handles, Camera, SceneView.

Editor类虽然可以使用OnSceneGUI来进行Scene视图里的各种定制操作,但是只能针对特定类型的脚本进行。如果想实现种怪这种编辑器常见需求,实现起来超级别扭。我尝试着基于Editor类来实现这个操作,发现除了在Inspector里锁住当前组件的视图外,没什么好方法了:创建一个空对象,放一个特定的类,实现一个特定的Editor,再每次编辑场景数据时手动锁定Inspector....想想都吐血了。

因此不可避免的寻求其他解决方案:EditorWindow

EditorWindowNamespace: UnityEditor
Parent class: ScriptableObject

Description

Derive from this class to create an editor window.

Create your own custom editor window that can float free or be docked as a tab, just like the native windows in the Unity interface.

关于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 确是一直在调用,所以加上这个之后,操作的反馈就变成实时的了,这会带来效率损耗---如果不影响操作的话,不用管。




你可能感兴趣的:(Unity3D)