Unity从文本文件读取坐标移动Cube时触发FormatException问题求助
解决Cube移动时的FormatException问题
嘿,我来帮你搞定这个头疼的格式转换错误!先拆解问题根源,再给你改好的代码和排查步骤。
你的代码核心问题
- 每帧重复读取文件:
Update()每帧都会执行,你每次都重新打开、读取文件,不仅浪费性能,还会导致读取结果无法保留(每次都新建列表)。 - 缺少错误校验:直接用
Convert.ToSingle转换字符串,一旦文本里有空行、多余空格、小数点格式错误,就会触发异常,还没法定位问题出在哪一行。
修正后的完整代码
using System.Collections.Generic; using System.Globalization; using System.IO; using UnityEngine; public class Cube : MonoBehaviour { // 移动速度 public float speed = 3.0f; // 存储所有目标坐标 private List<Vector3> targetPositions = new List<Vector3>(); // 当前要移动到的目标点索引 private int currentTargetIndex = 0; void Start() { print("cube says hi"); // 仅在启动时读取一次文件 LoadTargetPositions(); } // 专门处理文件读取的方法 void LoadTargetPositions() { // 注意:Unity标准资源文件夹是Resources,如果你确实用Ressources就改回路径 string path = "Assets/Resources/test.txt"; // 先检查文件是否存在,避免找不到文件的错误 if (!File.Exists(path)) { Debug.LogError($"找不到文件:{path},请检查路径拼写!"); return; } try { using (var sr = new StreamReader(path)) { while (!sr.EndOfStream) { string line = sr.ReadLine(); // 跳过空行,避免处理无效内容 if (string.IsNullOrWhiteSpace(line)) continue; var values = line.Split(new string[] { " " }, System.StringSplitOptions.RemoveEmptyEntries); // 确保一行有且只有三个数值 if (values.Length != 3) { Debug.LogWarning($"跳过无效行:{line},需要三个空格分隔的数值"); continue; } // 用TryParse安全转换,避免格式错误直接崩溃 if (float.TryParse(values[0], NumberStyles.Float, CultureInfo.InvariantCulture, out float x) && float.TryParse(values[1], NumberStyles.Float, CultureInfo.InvariantCulture, out float y) && float.TryParse(values[2], NumberStyles.Float, CultureInfo.InvariantCulture, out float z)) { targetPositions.Add(new Vector3(x, y, z)); } else { Debug.LogError($"无法转换行内容:{line},请检查数值格式!"); } } } if (targetPositions.Count == 0) { Debug.LogWarning("没有读取到有效坐标,请检查test.txt内容!"); } } catch (IOException ex) { Debug.LogError($"读取文件出错:{ex.Message}"); } } void Update() { // 没有目标点或已走完所有点,直接返回 if (targetPositions.Count == 0 || currentTargetIndex >= targetPositions.Count) return; float step = speed * Time.deltaTime; Vector3 targetPos = targetPositions[currentTargetIndex]; transform.position = Vector3.MoveTowards(transform.position, targetPos, step); // 可选:到达当前目标后自动切换到下一个点 if (Vector3.Distance(transform.position, targetPos) < 0.01f) { currentTargetIndex++; if (currentTargetIndex < targetPositions.Count) { Debug.Log($"已到达目标点,切换到下一个:{targetPositions[currentTargetIndex]}"); } else { Debug.Log("所有目标点已走完!"); } } } }
关键改动说明
- 文件读取移到Start():只执行一次,避免重复IO操作,同时把坐标存在类字段中供Update复用。
- 路径拼写修正:你原来写的
Ressources是拼写错误,Unity默认资源文件夹为Resources,如果你的文件夹确实叫前者,记得改回路径。 - 内容校验:跳过空行、检查每行是否有三个数值,避免无效内容触发错误。
- 安全转换:用
float.TryParse代替Convert.ToSingle,即使某行格式错误,程序也不会崩溃,还能输出错误信息帮你定位问题。 - 自动切换目标点:实现了到达一个点后自动走到下一个的逻辑,你可以根据需求调整(比如循环走、停在最后一个点等)。
最后检查你的test.txt内容
确保文件每一行都是三个空格分隔的浮点数,示例格式:
1.45 3.258 4.256 2.5 4.1 5.3 -0.2 0 1.8
如果你的系统默认用逗号作为小数点(比如欧洲地区),一定要确保文件里用.,因为CultureInfo.InvariantCulture是以点作为小数点分隔符的。
内容的提问来源于stack exchange,提问作者Lae
相关产品推荐
相关产品推荐

