You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity加载日志文件时出现NullReferenceException的原因排查

分析并修复你的NullReferenceException问题

首先咱们直接说核心原因:当StreamReader读到文件末尾时,ReadLine()会返回null,这时候你尝试对null调用Replace()方法,自然就触发了NullReferenceException。

再仔细拆解你的代码逻辑,还有几个明显的问题放大了这个错误:

问题1:循环条件逻辑错误

你的循环条件是while (!text.Equals(null)),但如果text真的是null,调用Equals()方法本身就会先抛出空引用异常;而且初始text被赋值为" ",第一次循环一定会执行,但这时候你还没读取任何文件内容,逻辑顺序完全颠倒了。

问题2:重复读取且未处理文件末尾

你在循环里先执行了一次inputStream.ReadLine();——这行读取了一行内容但完全没处理,直接丢弃了;然后又执行text = inputStream.ReadLine().Replace(...)。当文件读到最后一行之后,第二次ReadLine()就会返回null,这时候对null调用Replace()就直接触发报错了。

修复后的完整代码

/* loading the record file */
private void LoadRecordFile(int selectedRecordFile) {
    Debug.Log(selectedRecordFile.ToString());
    string path = recordFilesArray[selectedRecordFile];
    Debug.Log(path);
    
    // 用using语句自动管理StreamReader资源,比手动Close更安全可靠
    using (StreamReader inputStream = new StreamReader(path))
    {
        char[] delimiter = { ',' };
        string text;
        // 先读取一行赋值给text,再判断是否为null,这是读取文件的标准正确逻辑
        while ((text = inputStream.ReadLine()) != null)
        {
            Debug.Log(text);
            // 循环已经保证text不为null,直接调用Replace即可
            string cleanedText = text.Replace("(", "").Replace(")", "");
            string[] values = cleanedText.Split(delimiter);
            
            // 增加格式检查:避免日志行格式错误导致索引越界
            if (values.Length >=7)
            {
                // 直接初始化结构体,比先声明再赋值更清晰
                Vector3 vec3 = new Vector3(
                    float.Parse(values[0]),
                    float.Parse(values[1]),
                    float.Parse(values[2])
                );
                Quaternion quaternion = new Quaternion(
                    float.Parse(values[3]),
                    float.Parse(values[4]),
                    float.Parse(values[5]),
                    float.Parse(values[6])
                );
                
                CarPositionList.Add(vec3);
                CarRotationList.Add(quaternion);
            }
            else
            {
                Debug.LogWarning($"发现无效日志行:{text},已跳过该行");
            }
        }
    } // using代码块结束后自动关闭inputStream,无需手动调用Close
}

关键修改点说明

  • 使用using语句管理流资源:它会自动在代码块结束时释放资源,彻底避免忘记关闭流导致的资源泄漏问题。
  • 修正循环读取逻辑:while ((text = inputStream.ReadLine()) != null)——先读取一行赋值给text,再判断是否为null,完美处理文件末尾的边界情况。
  • 移除无用的重复读取:原来的第一行inputStream.ReadLine()完全浪费了一行日志数据,现在去掉后能正确读取每一行内容。
  • 增加格式校验:避免日志文件中存在格式错误的行时,触发IndexOutOfRangeException,同时打印警告方便排查问题。
  • 显式初始化结构体:原来的代码未初始化Vector3和Quaternion,虽然C#结构体有默认值,但显式初始化更清晰,避免潜在的逻辑歧义。

内容的提问来源于stack exchange,提问作者Sascha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 13:27:37