96SEO 2026-02-19 17:18 35
message!);注这里特别说一下Console窗口有个Error

Pause按钮意思是如果输出了Error日志则暂停运行有时候策划会跑过来说他的Unity运行游戏的时候突然卡死了感觉就像发现了什么惊天大BUG其实是他点了Error
事实上Debug.Log的参数是object即System.Object
//TestClass事实上它是先执行了对象的ToString()方法然后再输出日志的我们override重写类的ToString()方法就可以自定义输出啦比如
string.Format(a:{0}\nb:{1}\nc:{2},
如果你看Debug类的源码就会发现它有一个接收两个参数的Debug.Log方法这第二个参数context可以帮我们定位到物体的实例
如果你的物体是一个还没实例化的预设的引用则它会直接定位到Project视图中的资源我们来做下实验。
NewBehaviourScript.cs脚本代码如下
Camera上把Cube.prefab预设拖给脚本的cubePrefab成员如下
我们上面打印出来的日志都是默认的颜色白色事实上我们可以打印出彩色的日志
实际项目中我们一般是需要把日志写成文件方便出错时通过日志来定位问题。
Unity提供了一个事件Application.logMessageReceived方便我们来监听日志打印这样我们就可以把日志的文本内容写到文件里存起来啦~
我们一般在游戏启动的入口脚本的Awake函数中去监听Application.logMessageReceived事件如下
监听日志回调Application.logMessageReceived
Unity提供了一个可读写的路径给我们访问Application.persistentDataPath我们可以把日志文件存到这个路径下。
注Application.persistentDataPath在不同平台下的路径
WindowsC:/Users/用户名/AppData/LocalLow/CompanyName/ProductName
Mac/Users/用户名/Library/Caches/CompanyName/ProductName
iOS/var/mobile/Containers/Data/Application/APP名称/Documents
需要注意iOS的需要越狱并且使用Filza软件才能查看文件路径哦
使用StringBuilder来优化字符串的重复构造StringBuilder
System.DateTime.Now.ToString(yyyyMMddhhmmss);m_logFileSavePath
string.Format({0}/output_{1}.log,
Application.persistentDataPath,
t);Debug.Log(m_logFileSavePath);Application.logMessageReceived
OnLogCallBack;Debug.Log(日志存储测试);}///
type){m_logStr.Append(condition);m_logStr.Append(\n);m_logStr.Append(stackTrace);m_logStr.Append(\n);if
(!File.Exists(m_logFileSavePath)){var
File.Create(m_logFileSavePath);fs.Close();}using
File.AppendText(m_logFileSavePath)){sw.WriteLine(m_logStr.ToString());}m_logStr.Remove(0,
}我们可以在Application.persistentDataPath路径下看到日志文件
上传文件我们可以使用UnityWebRequest来处理这里需要注意我们的日志文件可能很小也可能很大正常情况下都比较小但是有时候报错了是会循环打印日志的导致日志文件特别大所以我们要考虑到大文件读取的情况否则读取日志文件时会很卡建议使用字节流读取。
塞入描述字段字段名与服务端约定好form.AddField(desc,
塞入日志字节流字段字段名与服务端约定好form.AddBinaryData(logfile,
使用UnityWebRequestUnityWebRequest
(!string.IsNullOrEmpty(request.error)){GameLogger.LogError(request.error);}else{GameLogger.Log(日志上传完毕,
request.downloadHandler.text);}request.Dispose();
StartCoroutine(HttpPost(http://你的web服务器,
实际项目中我们可能需要做日志开关比如开发阶段日志开启正式发布后则关闭日志。
Unity并没有给我们提供一个日志开关的功能那我们就自己封装一下吧~
return;Debug.LogWarning(message,
}我们所有使用Debug打印日志的地方都是改用GameLogger来打印这样就可以统一通过GameLogger来开关日志的打印了~不过这里会有一个问题就是我们在Console日志窗口双击日志的时候它只会跳转到GameLogger里而不是跳转到我们调用GameLogger的地方。
Start(){GameLogger.Log(哈哈哈哈哈);}
}看它是跳到GameLogger里而不是跳到我们的Test脚本了这个是显然的但我们能不能让它跳到Test脚本里呢
方法二通过反射分析日志窗口的堆栈拦截Unity日志窗口的打开文件事件跳转到我们指定的代码行处。
事实上我们写的C#代码都会被Unity编译成dll放在工程中默认是Assembly-CSharp.dll
注ILSpy反编译工具可以从GitHub下载https://github.com/icsharpcode/ILSpy
不过我们看到这个dll包含了其他的C#代码我们能不能专门只为GameLogger生成一个dll呢可以滴只需要把GameLogger.cs单独放在一个子中就可以看到生成了一个GameLogger.dll啦
把它剪切到Unity工程的Plugins目录中把我们的GameLogger.cs脚本删掉或是移动到工程外备份Assembly
这样就大功告成了我们测试一下日志双击溯源如下可以看到现在可以正常跳转到我们想要的地方了。
GameLogger.cs封装Debug日志打印实现日志开关控制、彩色日志打印、日志文件存储等功能LogUploader.cs实现日志上传到服务器的功能Main.cs程序入口脚本同时实现UI界面交互。
原理我上文都有讲这里就不赘述代码细节了可以看注释我都写得比较详细。
封装Debug日志打印实现日志开关控制、彩色日志打印、日志文件存储等功能
博客https://blog.csdn.net/linxinfa
使用StringBuilder来优化字符串的重复构造private
初始化在游戏启动的入口脚本的Awake函数中调用GameLogger.Init///
System.DateTime.Now.ToString(yyyyMMddhhmmss);s_logFileSavePath
string.Format({0}/output_{1}.log,
Application.persistentDataPath,
t);Application.logMessageReceived
type){s_logStr.Append(condition);s_logStr.Append(\n);s_logStr.Append(stackTrace);s_logStr.Append(\n);if
(!File.Exists(s_logFileSavePath)){var
File.Create(s_logFileSavePath);fs.Close();}using
File.AppendText(s_logFileSavePath)){sw.WriteLine(s_logStr.ToString());}s_logStr.Remove(0,
desc){LogUploader.StartUploadLog(s_logFileSavePath,
nameargs可变参数根据format的格式传入匹配的参数例a,
return;Debug.Log(FmtColor(color,
return;Debug.Log(FmtColor(green,
return;Debug.Log(FmtColor(yellow,
return;Debug.Log(FmtColor(#00ffff,
return;Debug.LogFormat((string)FmtColor(color,
return;Debug.LogWarning(message,
string.Format(color{0}{1}/color,
string.Format(color{0}{1}/color,
string.Format(color{0}{1}/color{2},
UNITY_EDITOR[UnityEditor.Callbacks.OnOpenAssetAttribute(0)]static
(!string.IsNullOrEmpty(stackTrace)
stackTrace.Contains(GameLogger:Log)){//
System.Text.RegularExpressions.Regex.Match(stackTrace,
(.)\),System.Text.RegularExpressions.RegexOptions.IgnoreCase);string
(!pathLine.Contains(GameLogger.cs)){int
System.Convert.ToInt32(pathLine.Substring(splitIndex
Application.dataPath.Substring(0,
Application.dataPath.LastIndexOf(Assets));fullPath
跳转到目标代码的特定行UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(fullPath.Replace(/,
typeof(UnityEditor.EditorWindow).Assembly.GetType(UnityEditor.ConsoleWindow);//
ConsoleWindowType.GetField(ms_ConsoleWindow,System.Reflection.BindingFlags.Static
|System.Reflection.BindingFlags.NonPublic);var
((object)UnityEditor.EditorWindow.focusedWindow
ConsoleWindowType.GetField(m_ActiveText,System.Reflection.BindingFlags.Instance
|System.Reflection.BindingFlags.NonPublic);//
fieldInfo.GetValue(consoleInstance).ToString();return
博客https://blog.csdn.net/linxinfa
http://127.0.0.1:7890/upload_log.php;public
go.AddComponentLogUploader();bhv.StartCoroutine(bhv.UploadLog(logFilePath,
Path.GetFileName(logFilePath);var
ReadLogFile(logFilePath);WWWForm
塞入描述字段字段名与服务端约定好form.AddField(desc,
塞入日志字节流字段字段名与服务端约定好form.AddBinaryData(logfile,
使用UnityWebRequestUnityWebRequest
(!string.IsNullOrEmpty(request.error)){GameLogger.LogError(request.error);}else{GameLogger.Log(日志上传完毕,
request.downloadHandler.text);}request.Dispose();}private
File.OpenRead(logFilePath)){int
监听日志输出到logText中Application.logMessageReceived
(!GameLogger.s_warningLogEnable)
;uploadBtn.onClick.AddListener(()
{GameLogger.UploadLog(上传日志测试);});logBtn.onClick.AddListener(()
{GameLogger.Log(打印一行日志);});logEnableTgl.onValueChanged.AddListener((v)
v;});GameLogger.Log(大家好我是林新发);GameLogger.LogCyan(我的CSDN博客https://blog.csdn.net/linxinfa);GameLogger.LogYellow(欢迎关注、点赞感谢支持~);GameLogger.LogRed(❤❤❤❤❤❤❤❤❤❤❤);}
给MainPanel.prefab预设挂上Main.cs脚本并赋值UI成员如下
我们的日志要上传到Web服务器所以我们需要搭建一个Web服务器。
简单的做法是使用PHP小皮~
关于小皮可以看我之前写的这篇文章https://blog.csdn.net/linxinfa/article/details/103033142
这样我们就已经启动了一个Web服务器了通过http://127.0.0.1:7890即可访问
我们打开Web服务器的根中创建一个upload_log.php
Assets/Scripts/GameLogger/GameLogger.cs:72)
Assets/Scripts/Main.cs:70)color#00ffff我的CSDN博客https://blog.csdn.net/linxinfa/color
Assets/Scripts/GameLogger/GameLogger.cs:131)
Assets/Scripts/Main.cs:71)coloryellow欢迎关注、点赞感谢支持~/color
Assets/Scripts/GameLogger/GameLogger.cs:122)
Assets/Scripts/Main.cs:72)colorred❤❤❤❤❤❤❤❤❤❤❤/color
Assets/Scripts/GameLogger/GameLogger.cs:104)
Assets/Scripts/Main.cs:73)打印一行日志
Assets/Scripts/GameLogger/GameLogger.cs:72)
UnityEngine.EventSystems.EventSystem:Update
Library/PackageCache/com.unity.ugui1.0.0/Runtime/EventSystem/EventSystem.cs:501)打印一行日志
Assets/Scripts/GameLogger/GameLogger.cs:72)
UnityEngine.EventSystems.EventSystem:Update
Library/PackageCache/com.unity.ugui1.0.0/Runtime/EventSystem/EventSystem.cs:501)打印一行日志
Assets/Scripts/GameLogger/GameLogger.cs:72)
UnityEngine.EventSystems.EventSystem:Update
Library/PackageCache/com.unity.ugui1.0.0/Runtime/EventSystem/EventSystem.cs:501)打印一行日志
Assets/Scripts/GameLogger/GameLogger.cs:72)
UnityEngine.EventSystems.EventSystem:Update
Library/PackageCache/com.unity.ugui1.0.0/Runtime/EventSystem/EventSystem.cs:501)打印一行日志
Assets/Scripts/GameLogger/GameLogger.cs:72)
UnityEngine.EventSystems.EventSystem:Update
Library/PackageCache/com.unity.ugui1.0.0/Runtime/EventSystem/EventSystem.cs:501)6、工程源码
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback