自己做的一个可视化log界面,本来用NGUI写更方便,考虑到有时候不用NGUI,所以用GUI写的,先上几张图:
基本上就是unity3d编辑器的console的一个实现,如图1,上面有个组选,可以在log,warining,error间切换,下面是每一条log信息,点击之后最下面就是调用栈,
C键可以清除当前log类型的所有信息,X键可以最小化,最小化后界面左上角有个小图标可以点击再显示,整个窗口可以拖动。
要使用它只用把脚本挂在一个场景中的物体上就行,当然也可以代码调用,并可以设置宽高,默认是全屏大小的。
下面上代码:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
/// <summary>
/// 可视DEBUG
/// </summary>
public class VisualLog4U3D : MonoBehaviour {
#region XXX
class StrPare{
public string Str1;
public string Str2;
public StrPare(string s1,string s2){
Str1 = s1;
Str2 = s2;
}
}
static List<StrPare> lst_log = new List<StrPare>();
static List<StrPare> lst_warming = new List<StrPare>();
static List<StrPare> lst_error = new List<StrPare>();
private bool show = true;
public bool showLog = true, showWarning = true, showError = true, autoSave = false;
public int MaxLine = 100;
void Awake() {
if (MaxLine > 999)
MaxLine = 999;
SetWHByScale(1,1);
Application.RegisterLogCallback(HandleLog);
curLst = lst_log;
}
//系统debug回调
void HandleLog(string logString, string stackTrace, LogType type) {
List<StrPare> tlst = lst_error;
switch (type) {
case LogType.Log:
tlst = lst_log;
break;
case LogType.Warning:
tlst = lst_warming;
break;
}
addList<StrPare>(tlst, new StrPare(logString, stackTrace), 100);
}
int index = 0;
int lastIndex = 0;
Rect rootRect;
List<StrPare> curLst;
void OnGUI() {
if (!show) {
GUILayout.FlexibleSpace();
if(GUILayout.Button("show",GUILayout.Width(Screen.width/5),GUILayout.Height(Screen.height/20))){
SwitchLog(true);
}
return;
}else
rootRect = GUI.Window(0, rootRect, rootWinFunc, new GUIContent("VisualLog4U3D"));
}
int w = 0;
int h = 0;
void rootWinFunc(int id) {
GUI.BeginGroup(new Rect(10,20,rootW - 10*2,rootH - 20 * 2));
if(w == 0)
w = rootW - 10 * 2;
if(h == 0)
h = rootH - 20 * 2;
index = GUI.Toolbar(new Rect(0, 0, w - h / 5f, h / 10f), index, new string[] { "log_"+lst_log.Count, "warning_"+lst_warming.Count, "error_"+lst_error.Count });
if (lastIndex != index) {
traceStr = "";
lastIndex = index;
switch (index) {
case 0:
curLst = lst_log;
break;
case 1:
curLst = lst_warming;
break;
case 2:
curLst = lst_error;
break;
}
}
if (GUI.Button(new Rect(w - h / 5f, 0, h / 10f, h / 10f), "C")) {
curLst.Clear();
traceStr = "";
}
if (GUI.Button(new Rect(w - h / 5f + h / 10f, 0, h / 10f, h / 10f), "X")) {
SwitchLog(false);
}
//Log
GUI.BeginGroup(new Rect(0, h / 10f+10, w, h / 2-10));
logWinFunc(2,w,h);
GUI.EndGroup();
//Trace
GUI.BeginGroup(new Rect(0, h / 10f * 6, w, h / 10f * 4));
traceWinFunc(3,w,h);
GUI.EndGroup();
GUI.EndGroup();
GUI.DragWindow(new Rect(0,0,Screen.width-10,Screen.height-10));
}
void logWinFunc(int id,int w,int h) {
Vector2 scrollPos = Vector2.zero;
scrollPos = GUI.BeginScrollView(new Rect(0, 0, w , h / 2), scrollPos, new Rect(0, 0, w, h / 20 * curLst.Count));
for (int i = 0; i < curLst.Count;i++ ) {
if(GUI.Button(new Rect(0,0 + i*h/20f,w -20,h/20f),i.ToString()+" "+curLst[i].Str1)){
traceStr = curLst[i].Str2;
}
}
GUI.EndScrollView();
}
string traceStr = "";
Vector2 scrollPos = Vector2.zero;
void traceWinFunc(int id,int w,int h) {
scrollPos = GUI.BeginScrollView(new Rect(0, 0, w, h / 10f * 4), scrollPos, new Rect(0, 0, w, h));
GUI.TextArea(new Rect(0, 0, w-20, h), traceStr);
GUI.EndScrollView();
}
static void addList<T>(List<T> lst,T val,int maxCount) {
while(lst.Count>=maxCount){
lst.RemoveAt(0);
}
lst.Add(val);
}
#endregion
static int rootW, rootH;
public VisualLog4U3D Get() {
var inst = GameObject.FindObjectOfType<VisualLog4U3D>();
if (inst == null) {
GameObject VisualLog = new GameObject("VisualLog4U3D");
inst = VisualLog.AddComponent<VisualLog4U3D>();
}
return inst;
}
public void SwitchLog(bool on_off) {
this.show = on_off;
}
public void SetWHByScale(float sx,float sy) {
rootW = (int)(Screen.width * sx);
rootH = (int)(Screen.height * sy);
rootRect = new Rect(0, 0, rootW, rootH);
}
}