【GEngine】Unity脚本框架、Custom Inspector

【转载请注明出处】

BaseBehaviour(基本组件)、BaseBehaviourContainer(基本组件容器,只在编辑器下生效)、BaseScript(基本脚本,对底层接口隐藏,逻辑脚本基类)

BaseScript:主要作用是脚本统一管理,以及批处理等。  

BaseBehaviourContainer:主要作用是自定义Inspector,并支持同一脚本中进行逻辑和CustomInspector的编写,同时不用暴露变量给Inspector。


效果预览:



BaseBehaviour类:

#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using System;
using System.Collections;

[ExecuteInEditMode]
#if UNITY_EDITOR
[RequireComponent(typeof(BaseBehaviourContainer))]
#endif
public class BaseBehaviour : MonoBehaviour 
{
#if UNITY_EDITOR
	[SerializeField][HideInInspector]
	private BaseBehaviourContainer mBaseBehaviourContainer;
	private BaseBehaviourContainer baseBehaviourContainer
	{
		get
		{
			if(mBaseBehaviourContainer == null)
				mBaseBehaviourContainer = GetComponent<BaseBehaviourContainer>();
			return mBaseBehaviourContainer;
		}
	}

	[SerializeField][HideInInspector]
	private Editor mInspector;
	protected Editor inspector
	{
		get
		{
			if(mInspector == null)
				mInspector = Editor.CreateEditor(this);

			return mInspector;
		}
	}
#endif

	protected virtual void Awake()
	{
		try
		{
#if UNITY_EDITOR
			if(mBaseBehaviourContainer == null)
				baseBehaviourContainer.AddBaseBehaviour(this);
#endif
			OnAwake();
		}
		catch(Exception e)
		{
			Debug.LogException(e);
		}
		finally
		{
		}
	}

	protected virtual void OnAwake()
	{

	}

	protected virtual void OnDestroy()
	{
#if UNITY_EDITOR
		baseBehaviourContainer.RemoveBaseBehaviour(this);
#endif
		try
		{
			OnDestroyed();
		}
		catch(Exception e)
		{
			Debug.LogException(e);
		}
		finally
		{
		}
	}

	protected virtual void OnDestroyed()
	{
	}

#if UNITY_EDITOR
	#region //Inspector
	public virtual void InspectorGUI()
	{
		OnInspectorGUI();
	}

	protected virtual void OnInspectorGUI()
	{	
		inspector.DrawDefaultInspector();
	}
	#endregion //Inspector

	#region //Component
	protected virtual void ComponentMoveUp()
	{
		baseBehaviourContainer.MoveUpaseBehaviour(this);
	}

	protected virtual void ComponentMoveDown()
	{
		baseBehaviourContainer.MoveDownaseBehaviour(this);
	}
	#endregion //Component
#endif
}

BaseScript类:

#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using System.Collections;

public class BaseScript : BaseBehaviour
{
	sealed protected override void Awake ()
	{
		base.Awake ();
	}

	sealed protected override void OnDestroy ()
	{
		base.OnDestroy ();
	}

#if UNITY_EDITOR
	sealed public override void InspectorGUI ()
	{
		base.InspectorGUI ();
	}

	[ContextMenu("Move Up")]
	sealed protected override void ComponentMoveUp ()
	{
		base.ComponentMoveUp ();
	}
	
	[ContextMenu("Move Down")]
	sealed protected override void ComponentMoveDown ()
	{
		base.ComponentMoveDown ();
	}
#endif
}

BaseBehaviourContainer类:

#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.EventSystems;

[Serializable]
public sealed  class BaseBehaviourInfo
{
	public BaseBehaviour baseBehaviour;
	public bool showInspector = true;
	
	public BaseBehaviourInfo(BaseBehaviour baseBehaviour)
	{
		this.baseBehaviour = baseBehaviour;
	}
}

[ExecuteInEditMode]
[DisallowMultipleComponent]
public class BaseBehaviourContainer : MonoBehaviour, IEventSystemHandler
{
	[SerializeField][HideInInspector]
	private List<BaseBehaviourInfo> baseBehaviourInfos = new List<BaseBehaviourInfo>();

	public void AddBaseBehaviour(BaseBehaviour baseBehaviour)
	{
		baseBehaviour.hideFlags = HideFlags.HideInInspector;
		BaseBehaviourInfo info = new BaseBehaviourInfo(baseBehaviour);
		baseBehaviourInfos.Add(info);
	}

	public void RemoveBaseBehaviour(BaseBehaviour baseBehaviour)
	{
		for(int i = 0; i < baseBehaviourInfos.Count; i++)
		{
			BaseBehaviourInfo info = baseBehaviourInfos[i];
			if(info.baseBehaviour == baseBehaviour)
			{		
				baseBehaviourInfos.RemoveAt(i);
				break;
			}
		}
	}

	public void MoveUpaseBehaviour(BaseBehaviour baseBehaviour)
	{
		if(baseBehaviourInfos.Count < 2)
			return;

		for(int i = 0; i < baseBehaviourInfos.Count; i++)
		{
			BaseBehaviourInfo info = baseBehaviourInfos[i];
			if(info.baseBehaviour == baseBehaviour)
			{
				if(i > 0)
				{
					BaseBehaviourInfo tempInfo = baseBehaviourInfos[i - 1];
					baseBehaviourInfos[i - 1] = info;
					baseBehaviourInfos[i] = tempInfo;
				}
				break;
			}
		}
	}

	public void MoveDownaseBehaviour(BaseBehaviour baseBehaviour)
	{
		if(baseBehaviourInfos.Count < 2)
			return;

		for(int i = 0; i < baseBehaviourInfos.Count; i++)
		{
			BaseBehaviourInfo info = baseBehaviourInfos[i];
			info.baseBehaviour.hideFlags = HideFlags.HideInInspector;
			if(info.baseBehaviour == baseBehaviour)
			{
				if(i < baseBehaviourInfos.Count - 1)
				{
					BaseBehaviourInfo tempInfo = baseBehaviourInfos[i + 1];
					baseBehaviourInfos[i + 1] = info;
					baseBehaviourInfos[i] = tempInfo;
				}
				break;
			}
		}
	}

	private void Update()
	{
		if(baseBehaviourInfos.Count > 0)
			return;

		BaseBehaviour[] baseBehaviours = GetComponents<BaseBehaviour>();
		for(int i = 0; i < baseBehaviours.Length; i++)
			AddBaseBehaviour(baseBehaviours[i]);

		if(baseBehaviourInfos.Count == 0)
			DestroyImmediate(this);
	}

	public void OnInspectorGUI()
	{
		GUILayout.Space(6);
		
		for(int i = 0; i < baseBehaviourInfos.Count; i++)
		{
			BaseBehaviourInfo info = baseBehaviourInfos[i];
			//创建Prefab时原组件不能自动隐藏,需要在这隐藏掉,assetimport时不能获取到组件,
			//并且project中inspector渲染稍慢一点,所以创建prefab后会闪一下
			//暂时不清楚序列化完成的内置事件
			info.baseBehaviour.hideFlags = HideFlags.HideInInspector;
			try
			{
				EditorTools.DrawBaseBehaviourTitlebar(info);
				if(info.showInspector)
				{
					EditorTools.BeginContents();
					info.baseBehaviour.InspectorGUI();
					EditorTools.EndContents(); 
				}
			}
			catch(Exception e)
			{	
				//ToDo
				//双击引用时可能会异常,没有使用正常的结束组,如GUILayout.EndHorizontal(),但目前无影响
				if(e.GetType().Name != "ExitGUIException")
					Debug.LogException(e);
			}
			finally
			{
			}
		}
	}
}
#endif

BaseBehaviourContainerInspector类:

using UnityEngine;
using System.Collections;
using UnityEditor;
using System;

[CustomEditor(typeof(BaseBehaviourContainer))]
public sealed class BaseBehaviourContainerInspector : Editor
{
	BaseBehaviourContainer baseBehaviourContainer;
	void OnEnable()
	{
		baseBehaviourContainer = target as BaseBehaviourContainer; 
	}

	public override void OnInspectorGUI ()
	{
		baseBehaviourContainer.OnInspectorGUI (); 
	} 
}

EditorTools类(根据NGUI改动):

#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using System.Collections;

public class EditorTools 
{
	public class EditorSettings
	{
		/// <summary>
		/// Get the previously saved boolean value.
		/// </summary>
		
		static public bool GetBool (string name, bool defaultValue) { return EditorPrefs.GetBool(name, defaultValue); }

		/// <summary>
		/// Save the specified boolean value in settings.
		/// </summary>
		
		static public void SetBool (string name, bool val) { EditorPrefs.SetBool(name, val); }

		static public bool minimalisticLook
		{
			get { return GetBool("NGUI Minimalistic", false); }
			set { SetBool("NGUI Minimalistic", value); }
		}
	}

	/// <summary>
	/// Draw a distinctly different looking header label
	/// </summary>
	
	static public bool DrawHeader (string text) { return DrawHeader(text, text, false, EditorSettings.minimalisticLook); }

	/// <summary>
	/// Draw a distinctly different looking header label
	/// </summary>
	
	static public bool DrawHeader (string text, bool detailed) { return DrawHeader(text, text, detailed, !detailed); }

	/// <summary>
	/// Draw a distinctly different looking header label
	/// </summary>
	
	static public bool DrawHeader (string text, string key, bool forceOn, bool minimalistic)
	{
		bool state = EditorPrefs.GetBool(key, true);
		
		if (!minimalistic) GUILayout.Space(3f);
		if (!forceOn && !state) GUI.backgroundColor = new Color(0.8f, 0.8f, 0.8f);
		GUILayout.BeginHorizontal();
		GUI.changed = false;
		
		if (minimalistic)
		{
			if (state) text = "\u25BC" + (char)0x200a + text;
			else text = "\u25BA" + (char)0x200a + text;
			
			GUILayout.BeginHorizontal();
			GUI.contentColor = EditorGUIUtility.isProSkin ? new Color(1f, 1f, 1f, 0.7f) : new Color(0f, 0f, 0f, 0.7f);
			if (!GUILayout.Toggle(true, text, "PreToolbar2", GUILayout.MinWidth(20f))) state = !state;
			GUI.contentColor = Color.white;
			GUILayout.EndHorizontal();
		}
		else
		{
			text = "<b><size=11>" + text + "</size></b>";
			if (state) text = "\u25BC " + text;
			else text = "\u25BA " + text;
			if (!GUILayout.Toggle(true, text, "dragtab", GUILayout.MinWidth(20f))) state = !state;
		}
		
		if (GUI.changed) EditorPrefs.SetBool(key, state);
		
		if (!minimalistic) GUILayout.Space(2f);
		GUILayout.EndHorizontal();
		GUI.backgroundColor = Color.white;
		if (!forceOn && !state) GUILayout.Space(3f);
		return state;
	}

	/// <summary>
	/// Draw a distinctly different looking header BaseBehaviour
	/// </summary>
	
	static public void DrawBaseBehaviourTitlebar(BaseBehaviourInfo info)
	{
		GUILayout.BeginHorizontal("TE NodeBox");
		info.showInspector = EditorGUILayout.InspectorTitlebar(info.showInspector, info.baseBehaviour);
		GUILayout.EndHorizontal();
	}
	
	/// <summary>
	/// Begin drawing the content area.
	/// </summary>
	
	static public void BeginContents () { BeginContents(EditorSettings.minimalisticLook); }

	static bool mEndHorizontal = false;
	
	/// <summary>
	/// Begin drawing the content area.
	/// </summary>
	
	static public void BeginContents (bool minimalistic)
	{
		if (!minimalistic)
		{
			mEndHorizontal = true;
			GUILayout.BeginHorizontal();
			EditorGUILayout.BeginHorizontal("AS TextArea", GUILayout.MinHeight(10f));
		}
		else
		{
			mEndHorizontal = false;
			EditorGUILayout.BeginHorizontal(GUILayout.MinHeight(10f));
			GUILayout.Space(10f);
		}
		GUILayout.BeginVertical();
		GUILayout.Space(2f);
	}
	
	/// <summary>
	/// End drawing the content area.
	/// </summary>
	
	static public void EndContents ()
	{
		GUILayout.Space(3f);
		GUILayout.EndVertical();
		EditorGUILayout.EndHorizontal();
		
		if (mEndHorizontal)
		{
			GUILayout.Space(3f);
			GUILayout.EndHorizontal();
		}
		
		GUILayout.Space(3f);
	}
}
#endif

TestA、TestB、TestC测试类:

#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using System.Collections;

public class BaseTestA : BaseScript
{
	public float a;

#if UNITY_EDITOR
	protected override void OnInspectorGUI ()
	{
		base.OnInspectorGUI();
	}
#endif
}

#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using System.Collections;

[System.Serializable]
public class BaseTestB : BaseScript
{
	public Color colorEnter;
	public Color colorNormal;

#if UNITY_EDITOR
	protected override void OnInspectorGUI ()
	{
		base.OnInspectorGUI ();

		GUILayout.Label("这是自定义Inspector");
	}
#endif
}

using UnityEngine;
using System.Collections;

public class BaseTestC : BaseScript 
{
	public BaseTestA ta;
	public BaseTestB tb;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值