錯誤日誌
今天在 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 個字符的最長路徑