unity3d 加载卡顿,File.Exists 罪魁祸首之天坑

测试表明,在华为V10手机上,使用File.Exists检查文件存在性会导致显著的性能问题,尤其当目录中文件数量庞大时。判定文件不存在比存在耗时高出约100倍。在Unity引擎环境下,此方法同样消耗大量时间。最佳实践建议缓存结果或确保所有加载的文件确实存在。

File.Exists 是用来判定文件是否存在,然后进行加载的常用逻辑,但也是造成加载卡顿的 罪魁祸首,
这里测试,在华为v10 ,1加手机,会特别明显, 我用moto手机测试感觉没什么问题,也许跟手机装的app数量也有关系,总之对于这方法尽量避免使用,
下面说明一下这个方法的测试情况:

测试机器:华为v10
目录下文件数量:13749
判定不存在的文件:消耗30ms-45ms不等
判定存在的文件:消耗0.2ms~0.5ms不等
结果:大概快了100倍。
如果加载文件多,这些耗时加起来就一个大问题了

尝试测试unity引擎问题
测试机器:华为v10
目录下文件数量:14612
1、unity4 mono,File.Exists会消耗31~71ms
2、unity2017 mono, File.Exists会消耗30~50ms
3、unity2017 il2cpp, File.Exists会消耗30-45ms
4、unity2017 il2cpp 用FileInfo获取Exists属性 70~100ms
5、unity2017 il2cpp 用File.Open读取不存在的文件,40~90ms
6、android app,native C直接调用stat和lstat系统api,其中stat:1540ms,lstat:1540ms,合计30~80ms
7、android app,native C用fopen代替stat和lstat,判断打开成功与否,20~45ms,
结果:可以断定与unity4,unity2017,mono,il2cpp,都无关,

可知File.Exists在手机上存在很大的问题, 所以我们的次级解决方案是每做一次File.Exist的就进行标记缓存,避免多次加载同一个文件的时候造成多次伤害,最好的方案就是确保加载的文件都的一一存在的!!!!!!!!

### 问题分析 在Unity中,当发布到Linux平台时,`File.Exists` 方法可能返回错误的结果(即使文件路径正确),这通常是由于以下几个原因导致的: 1. **路径格式问题**:Linux是区分大小写的文件系统,因此路径中的任何大小写错误都会导致文件无法被找到。 2. **文件权限问题**:Linux对文件和目录有严格的权限控制。如果程序没有足够的权限访问目标文件或目录,`File.Exists` 将返回 `false`。 3. **相对路径与工作目录问题**:在Linux平台上,Unity的工作目录可能与预期不同,这会导致相对路径解析失败[^1]。 4. **符号链接问题**:如果目标文件是一个符号链接,而程序没有正确处理符号链接,也可能导致文件检测失败。 ### 解决方法 以下是针对上述问题的解决方法: #### 1. 确保路径大小写正确 Linux文件系统是严格区分大小写的。请检查路径字符串中的所有字母是否与实际文件名完全一致。例如,`/Assets/Example.txt` 和 `/assets/example.txt` 在Linux中会被视为两个不同的文件[^1]。 #### 2. 检查文件权限 使用Linux命令行工具检查目标文件的权限设置。可以通过以下命令查看文件权限: ```bash ls -l /path/to/file ``` 确保程序运行用户具有读取该文件的权限。如果没有权限,可以使用以下命令修改: ```bash chmod u+r /path/to/file ``` #### 3. 使用绝对路径 为了避免相对路径解析问题,建议始终使用绝对路径。可以通过以下代码获取当前工作目录并拼接文件路径: ```csharp string currentDirectory = System.Environment.CurrentDirectory; string fullPath = System.IO.Path.Combine(currentDirectory, "relative/path/to/file"); if (System.IO.File.Exists(fullPath)) { Debug.Log("File exists!"); } else { Debug.LogError("File does not exist!"); } ``` #### 4. 处理符号链接 如果目标文件是一个符号链接,需要确保程序能够正确解析符号链接。可以通过以下代码检查符号链接是否存在: ```csharp if (System.IO.File.Exists("/path/to/symlink")) { Debug.Log("Symbolic link exists and points to a valid file."); } else { Debug.LogError("Symbolic link is broken or does not exist."); } ``` #### 5. 调试路径问题 如果仍然无法确定问题所在,可以打印出路径进行调试: ```csharp Debug.Log($"Checking file at: {filePath}"); ``` 同时,确保路径中没有多余的空格或特殊字符。 ### 示例代码 以下是一个完整的示例代码,用于检查文件是否存在,并处理常见问题: ```csharp using System.IO; using UnityEngine; public class FileChecker : MonoBehaviour { void Start() { string filePath = "/absolute/path/to/file.txt"; // 替换为实际文件路径 // 检查文件是否存在 if (File.Exists(filePath)) { Debug.Log("File exists!"); } else { Debug.LogError("File does not exist!"); // 打印当前工作目录以调试路径问题 Debug.LogWarning($"Current working directory: {System.Environment.CurrentDirectory}"); } } } ``` ### 注意事项 - 如果文件位于 `StreamingAssets` 文件夹下,请注意 Unity 在不同平台上对 `StreamingAssets` 的处理方式不同。在Linux平台上,`StreamingAssets` 文件夹的内容会被打包为 `.assetbundle` 文件[^2]。 - 在Linux平台上,建议使用 `Application.streamingAssetsPath` 获取 `StreamingAssets` 文件夹的实际路径,并通过 `WWW` 或 `UnityWebRequest` 加载文件内容。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值