今天在 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: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 API 中,通过 MAX_PATH
来限制路径得最大长度,MAX_PATH
被定义为 260
一般路径得结构:
|盘符|冒号|反斜杠|被分斜杠分割的具体路径|NUL('\0')|
例如:D:\
最后的 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 个字符的最长路径
为什么Windows字符路径长度为260个字符?
Windows文件名长度限制