淘先锋技术网

首页 1 2 3 4 5 6 7

版本管理

需要版本管理的文件夹只有Assets、ProjectSettings和UnityPackageManager。

unity界面

切换pivot和center选项,可以在选中的一组对象(或有父子关系的对象)间切换轴点是自身还是中心。global和local可以切换对象的坐标系,方便移动。

修改game视图的分辨率,可以查看ui在不同分辨率中的表现。

编辑器扩展

Project窗口右键菜单

using UnityEngine;
using UnityEditor;
public class AssetsEditor {
	// 顶部工具栏Assets和Project窗口中右键资源时会显示此菜单
	[MenuItem("Assets/My Tools/Tools 1", false, 1)]
	static void MyTools(){
		Debug.Log(Selection.activeObject.name);
	}
}

Create创建菜单

using UnityEngine;
using UnityEditor;
public class AssetsEditor {
	// Create创建菜单,通过菜单路径(“Assets/Create”)识别
	[MenuItem("Assets/Create/My Create/Cube", false, 2)]
	static void CreateCube(){
		GameObject.CreatePrimitive(PrimitiveType.Cube);
	}
}

Project窗口中选中资源,右侧显示按钮等UI元素

using UnityEngine;
using UnityEditor;
public class AssetsEditor {
	// Project窗口中选中资源,右侧会出现按钮
	// [InitializeOnLoadMethod] 表示此方法会在C#代码每次编译完成后调用
	[InitializeOnLoadMethod]
	static void InitializeOnLoadMethod(){
		// 监听此方法可以绘制GUI
		EditorApplication.projectWindowItemOnGUI = delegate(string guid, Rect selectionRect){
			// 在Project窗口中选中一个资源
			if(Selection.activeObject && 
			guid == AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(Selection.activeObject))){
				// 设置拓展按钮区域
				float width = 50f;
				selectionRect.x += (selectionRect.width - width);
				selectionRect.y += 2f;
				selectionRect.width = width;
				GUI.color = Color.red;
				if(GUI.Button(selectionRect, "click")){
					Debug.LogFormat("click: {0}", Selection.activeObject.name);
				};
				GUI.color = Color.white;
			}
		};
	}
}

Project 窗口中的事件监听

可以监听资源创建、删除、移动和保存方法

using UnityEngine;
using UnityEditor;
// 继承 AssetModificationProcessor 可以监听资源创建、删除、移动和保存方法
public class MyAssetModification : UnityEditor.AssetModificationProcessor {
	[InitializeOnLoadMethod]
	static void InitializeOnLoadMethod(){
		// 全局监听Project 窗口资源是否发生改变(添加,删除,移动)
		EditorApplication.projectChanged += delegate(){
			Debug.Log("project window change");
		};
	}
	// 监听“双击鼠标左键,打开资源”事件
	public static bool IsOpenForEdit(string assetPath, out string message){
		message = null;
		Debug.LogFormat("IsOpenForEdit path: {0}", assetPath);
		// return true 表示资源可以打开,false表示不可以在unity中打开
		return true;
	}
	// 监听资源即将被创建
	public static void OnWillCreateAsset(string path){
		Debug.LogFormat("OnWillCreateAsset path: {0}", path);
	}
	// 监听资源将被删除
	public static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetOptions option){
		Debug.LogFormat("OnWillDeleteAsset delete: {0}", assetPath);
		// AssetDeleteResult.DidNotDelete 表示资源可以删除
		return AssetDeleteResult.DidNotDelete;
	}
}

Hierarchy 窗口扩展

添加Create菜单,添加对象右侧按钮

using UnityEditor;
using UnityEngine;
public class MyHierarchyEditor {
	// HierarchyEditor Creat按钮下的菜单都在GameObject路径下面
	[MenuItem("GameObject/My Create/Cube", false, 0)]
	static void CreateCube(){
		GameObject.CreatePrimitive(PrimitiveType.Cube);
	}
	// 选中 Hierarchy 中对象右侧显示按钮
	[InitializeOnLoadMethod]
	static void InitializeOnLoadMethod(){
		// 监听渲染回调
		EditorApplication.hierarchyWindowItemOnGUI = delegate(int instanceID, Rect selectionRect){
			if(Selection.activeObject && 
			instanceID == Selection.activeObject.GetInstanceID()){
				// 设置拓展按钮区域
				float width = 50f;
				float height = 20f;
				selectionRect.x += (selectionRect.width - width);
				selectionRect.width = width;
				selectionRect.height = height;
				if(GUI.Button(selectionRect, "click")){
					Debug.LogFormat("click: {0}", Selection.activeObject.name);
				};
			}
		};
	}
}

禁用对象(HideFlags)

设置对象的HideFlags 可以控制对象在编辑器中的销毁、保存和可见性。入下图对象处于不可编辑状态

using UnityEditor;
using UnityEngine;
public class MyHierarchyEditor {
	// 设置游戏对象锁定(hideFlags)
	[MenuItem("GameObject/3D Object/Lock/Lock", false, 0)]
	static void Lock(){
		if(Selection.gameObjects != null){
			foreach(var gameobject in Selection.gameObjects){
				gameobject.hideFlags = HideFlags.NotEditable;
			}
		}
	}
	[MenuItem("GameObject/3D Object/Lock/UnLock", false, 0)]
	static void UnLock(){
		if(Selection.gameObjects != null){
			foreach(var gameobject in Selection.gameObjects){
				gameobject.hideFlags = HideFlags.None;
			}
		}
	}
}

Inspector 窗口扩展

给Camera Inspector窗口添加按钮,扩展自定义组件时同理

using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(Camera))]
public class MyCameraEditor : Editor {
	// 重写 OnInspectorGUI 方法绘制
	public override void OnInspectorGUI(){
		if(GUILayout.Button("button")){
			Debug.Log("click");
		}
		base.OnInspectorGUI();
	}
}

组件添加Context 菜单,并且获取组件中的属性

using UnityEditor;
using UnityEngine;
public class MyHierarchyEditor {
	// 修改组件的Context 菜单
	// 路径中的 Transform 表示给Transform 组件添加菜单,Component 表示给所有组件添加
	[MenuItem("CONTEXT/Transform/New Context")]
	static void NewContext(MenuCommand command){
		Transform trans = command.context as Transform;
		Debug.Log("NewContext :" + trans.position);
	}
}

Scene 窗口扩展

依靠Gizmos 对象可以在Scene 窗口中绘制各种对象

给Camera 添加辅助图形,将绘制脚本添加到Camera对象上。由于不是Editor脚本,所以不可放在Editor文件夹下。

using UnityEngine;
public class CameraSceneExtend : MonoBehaviour{
	// 选中一个对象时绘制
	void OnDrawGizmosSelected(){
		Gizmos.color = Color.red;
		Gizmos.DrawLine(transform.position, Vector3.one);
		Gizmos.DrawCube(Vector3.one, Vector3.one);
	}
	// 无需选中对象即可绘制
	void OnDrawGizmos(){
		Gizmos.DrawSphere(transform.position, 1);
	}
}

Scene 窗口绘制UI

需继承 Editor 类在Scene 中绘制UI,需要注意的是重写Inspector 窗口和Scene 窗口都需要[CustomEditor(typeof(Camera))],这里需要写在一个编辑器脚本中,否则只会有一个生效

using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(Camera))]
public class MyCameraEditor : Editor {
	// 重写 OnInspectorGUI 方法绘制
	public override void OnInspectorGUI(){
		if(GUILayout.Button("button")){
			Debug.Log("click");
		}
		base.OnInspectorGUI();
	}
        // 绘制Scene 窗口
	void OnSceneGUI(){
		Camera camera = target as Camera;
		if(camera != null){
			Handles.color = Color.red;
			Handles.Label(camera.transform.position, camera.transform.position.ToString());
			// EditorGUI方法要放在Handles.BeginGUI 中
			Handles.BeginGUI();
			GUI.backgroundColor = Color.green;
			if(GUILayout.Button("click", GUILayout.Width(200f))){
				Debug.LogFormat("click = {0}", camera.name);
			}
			GUILayout.Label("Label.");
			Handles.EndGUI();
		}
	}
}

Scene 窗口中绘制常驻辅助UI和右键菜单

上面都是选中一个对象后在Scene 窗口中绘制,下面是常驻Scene 的绘制方式

using UnityEditor;
using UnityEngine;
public class MySceneUIEditor {
	[InitializeOnLoadMethod]
	static void InitializeOnLoadMethod(){
		// 全局监听SceneView.onSceneGUIDelegate 
		SceneView.onSceneGUIDelegate = delegate(SceneView sceneView){
			Handles.BeginGUI();
			GUI.Label(new Rect(0f, 0f, 50f, 15f), "标题");
			Handles.EndGUI();

			// 绘制右键菜单
			// 鼠标右键抬起
			Event e = Event.current;
			if(e != null && e.button == 1 && e.type == EventType.MouseUp){
				Vector2 mousePosition = e.mousePosition;
				var options = new GUIContent[]{
					new GUIContent("Test1"),
					new GUIContent(""),
					new GUIContent("Test/Test2"),
					new GUIContent("Test/Test3"),
				};
				var selected = -1;
				var userData = Selection.activeGameObject;
				var width = 100;
				var height = 100;
				var position = new Rect(mousePosition.x,mousePosition.y - height, width, height);
				EditorUtility.DisplayCustomMenu(position, options, selected,
					delegate(object data, string[] opt, int select){
						Debug.Log(opt[select]);
				}, userData);
				e.Use();
			}
		};
	}
}

Game 窗口扩展

需要在脚本类名上方使用[ExecuteInEditMode] ,这类脚本一般仅在编辑器中使用。

using UnityEngine;
#if UNITY_EDITOR
[ExecuteInEditMode]
public class MyCameraGameEditorUI : MonoBehaviour {
	void OnGUI () {
		if(GUILayout.Button("click")){
			Debug.Log("click");
		}
	}
}
#endif

EditorWindow  绘制自定义窗口

绘制窗口和窗口右上角的下拉菜单

using UnityEditor;
using UnityEngine;
// IHasCustomMenu 可以自定义窗口右上角的下拉菜单
public class MyEditorWindow : EditorWindow, IHasCustomMenu {
	// 打开窗口
	[MenuItem("Window/My Window")]
	static void Init(){
		MyEditorWindow window = (MyEditorWindow)EditorWindow.GetWindow(typeof(MyEditorWindow));
		window.Show();
	}
	void IHasCustomMenu.AddItemsToMenu(GenericMenu menu){
		menu.AddDisabledItem(new GUIContent("Disable"));
		menu.AddItem(new GUIContent("Test1"), true, () => {
			Debug.Log("Test1");
		});
		menu.AddSeparator("Test/");
		menu.AddItem(new GUIContent("Test/Test2"), true, () => {
			Debug.Log("Test2");
		});
	}
}

绘制预览窗口,Inspector 窗口下方

默认cube是没有预览信息的

using UnityEditor;
using UnityEngine;
[CustomPreview(typeof(GameObject))]
public class MyObjectPreview : ObjectPreview {
	public override bool HasPreviewGUI(){
		return true;
	}
	public override void OnPreviewGUI(Rect r, GUIStyle background){
		GUILayout.Label("label");
	}
}