Unity Windows 路径长度限制踩坑
Posted 河乐不为
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity Windows 路径长度限制踩坑相关的知识,希望对你有一定的参考价值。
错误日志
今天在 Windows 上打 PC 包时遇到了这样的报错:
Console 输出的详细错误日志:
IOException: Failed to Move File / Directory from 'Temp/StagingArea\\bunny rummy_Data\\StreamingAssets\\lua\\logic\\ui\\pnl_activity\\first_add_cash\\first_add_cash_activity_preselected_item\\ui_first_add_cash_activity_preselected_item_logic.lua' to 'C:\\TS\\rummy_itc\\Assets\\..\\z_package\\debug\\bunny_rummy_8-3-3-4_v1.0.1.20_20200427_153115\\bunny rummy_Data\\StreamingAssets\\lua\\logic\\ui\\pnl_activity\\first_add_cash\\first_add_cash_activity_preselected_item\\ui_first_add_cash_activity_preselected_item_logic.lua'.
UnityEditor.FileUtil.MoveFileOrDirectory (System.String source, System.String dest) (at C:/buildslave/unity/build/Editor/Mono/FileUtil.bindings.cs:77)
DesktopStandalonePostProcessor.CopyFilesToDestination (System.String source, System.String target, System.Collections.Generic.HashSet`1[T] filesToNotOverwrite) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs:428)
DesktopStandalonePostProcessor.CopyFilesToDestination (System.String source, System.String target, System.Collections.Generic.HashSet`1[T] filesToNotOverwrite) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs:432)
DesktopStandalonePostProcessor.CopyFilesToDestination (System.String source, System.String target, System.Collections.Generic.HashSet`1[T] filesToNotOverwrite) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs:432)
DesktopStandalonePostProcessor.CopyFilesToDestination (System.String source, System.String target, System.Collections.Generic.HashSet`1[T] filesToNotOverwrite) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs:432)
DesktopStandalonePostProcessor.CopyFilesToDestination (System.String source, System.String target, System.Collections.Generic.HashSet`1[T] filesToNotOverwrite) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs:432)
DesktopStandalonePostProcessor.CopyFilesToDestination (System.String source, System.String target, System.Collections.Generic.HashSet`1[T] filesToNotOverwrite) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs:432)
DesktopStandalonePostProcessor.CopyFilesToDestination (System.String source, System.String target, System.Collections.Generic.HashSet`1[T] filesToNotOverwrite) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs:432)
DesktopStandalonePostProcessor.CopyFilesToDestination (System.String source, System.String target, System.Collections.Generic.HashSet`1[T] filesToNotOverwrite) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs:432)
DesktopStandalonePostProcessor.CopyFilesToDestination (System.String source, System.String target, System.Collections.Generic.HashSet`1[T] filesToNotOverwrite) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs:432)
DesktopStandalonePostProcessor.CopyStagingAreaIntoDestination (UnityEditor.Modules.BuildPostProcessArgs args, System.Collections.Generic.HashSet`1[T] filesToNotOverwrite) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs:402)
DesktopStandalonePostProcessor.PostProcess (UnityEditor.Modules.BuildPostProcessArgs args) (at C:/buildslave/unity/build/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs:51)
UnityEditor.BuildPipeline:BuildPlayer(String[], String, BuildTarget, BuildOptions)
PackAppPatch:GenPackage() (at Assets/Code/Editor/Package/PackAppPatch.cs:342)
PackAppPatch:DoPackApp(CPackArg) (at Assets/Code/Editor/Package/PackAppPatch.cs:203)
PackGUI:OnClickPackage() (at Assets/Code/Editor/Package/PackGUI.cs:54)
PackGUI:BranchConfirm(Action) (at Assets/Code/Editor/Package/PackGUI.cs:311)
<>c__DisplayClass9_0:<OnGUI>b__1() (at Assets/Code/Editor/Package/PackGUI.cs:112)
GuiUtil:RegSceneBtn(String, String, Action) (at Assets/Code/Editor/GuiUtil.cs:30)
PackGUI:OnGUI() (at Assets/Code/Editor/Package/PackGUI.cs:110)
PackGUI:Draw() (at Assets/Code/Editor/Package/PackGUI.cs:23)
UtilTemplate`2:OnGUI() (at Assets/Code/Editor/UtilBase/UtilTemplate.cs:55)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
看起来貌似是拷贝文件时拷贝失败了,核心的报错内容是这部分:
IOException: Failed to Move File / Directory from 'Temp/StagingArea\\bunny rummy_Data\\StreamingAssets\\lua\\logic\\ui\\pnl_activity\\first_add_cash\\first_add_cash_activity_preselected_item\\ui_first_add_cash_activity_preselected_item_logic.lua' to 'C:\\TS\\rummy_itc\\Assets\\..\\z_package\\debug\\bunny_rummy_8-3-3-4_v1.0.1.20_20200427_153115\\bunny rummy_Data\\StreamingAssets\\lua\\logic\\ui\\pnl_activity\\first_add_cash\\first_add_cash_activity_preselected_item\\ui_first_add_cash_activity_preselected_item_logic.lua'.
UnityEditor.FileUtil.MoveFileOrDirectory (System.String source, System.String dest) (at C:/buildslave/unity/build/Editor/Mono/FileUtil.bindings.cs:77)
即调用 UnityEditor.FileUtil.MoveFileOrDirectory
API 去复制文件的时候出错了
错误分析
其实之前出现过,使用相同内容的工程打包,在 C 盘下的工程可以打包,在 E 盘下不能打包,区别就是路径不同,如下:
-
C 盘工程路径:
C:\\TS\\rummy_itc
-
D 盘工程路径:
E:\\U3DProjects\\rummy_itc_copy
显然路径长度不同,只是 C 盘可以打包成功了就暂时没去理会。
这次 C 盘的工程也出现打包问题了,而且可以看到报错的路径长度很长,特别是复制目标文件的路径 'C:\\TS\\rummy_itc\\Assets\\..\\z_package\\debug\\bunny_rummy_8-3-3-4_v1.0.1.20_20200427_153115\\bunny rummy_Data\\StreamingAssets\\lua\\logic\\ui\\pnl_activity\\first_add_cash\\first_add_cash_activity_preselected_item\\ui_first_add_cash_activity_preselected_item_logic.lua'
,使用在线计算工具统计的结果:
字符长度为 256,初步猜测是路径超过 Windows 路径的长度限制。
Windows 限制
在 Windows API 中,通过 MAX_PATH
来限制路径得最大长度,MAX_PATH
被定义为 260
一般路径得结构:
|盘符|冒号|反斜杠|被分斜杠分割的具体路径|NUL('\\0')|
例如:D:\\<dir>NUL
最后的 NUL
是终止符,也可以用 '\\0'
表示 ,因此,去除盘符的目录的相对路径 dir 长度不能超过 256,这里对于目录和文件的限制有所区别:
-
目录:248
-
文件:256
Windows API 中会将
'/'
转为'\\'
测试
将上面报错的目标路径修改进行测试,测试代码如下:
String src = "Temp/StagingArea/bunny rummy_Data/StreamingAssets/lua/logic/ui/pnl_activity/first_add_cash/first_add_cash_activity_preselected_item/ui_first_add_cash_activity_preselected_item_logic.lua";
String des = "C:/TS/rummy_itc/Assets/../z_package/debug/bunny_rummy_8-3-3-4_v1.0.1.20_20200427_105542/bunny rummy_Data/StreamingAssets/lua/logic/ui/pnl_activity/first_add_cash/first_add_cash_activity_preselected_item/ui_first_add_cash_activity_preselected_item_logic.lua";
FileUtil.CopyFileOrDirectory(src, des);
测试结果是将文件名删除一部分,改为 ui_first_add_cash_activity_preselected_item_
,最终总路径长度为 247 才能复制成功。
总结
像这样的问题只能在开发时,通过一些规范来规避,主要需要注意几点:
-
Unity 工程位置不要放得太深,尽量放在磁盘根路径下或二级路径,如 :D:\\U3DProjs
-
工程内文件名不要太长,像
ui_first_add_cash_activity_preselected_item_logic.lua
这样的取名方式有点逆天了,尽量用缩写 -
工程内目录不要创建太多级,且目录名不要太长
其他
MSDN 提到,可以通过 "\\\\?\\"
前缀加上至多 255 长度的字符串来表示长达 32000 个字符的最长路径
参考
以上是关于Unity Windows 路径长度限制踩坑的主要内容,如果未能解决你的问题,请参考以下文章