Swift中RoomPlan API生成USDZ转FBX失败,请求代码排查
USDZ转FBX失败排查(OBJ转换正常)
我通过RoomPlan API生成了USDZ文件,需在Unity中使用,但Unity不支持USDZ格式,因此需要将其转换为FBX与OBJ格式。目前OBJ转换正常,但FBX转换失败,目标路径为空,烦请帮忙排查以下代码:
let inputFileName = "Rom2.usdz"//"plantpot.usdz" let outputFileName = "Rom3.obj"//"Rom3.fbx" override func viewDidLoad() { super.viewDidLoad() let fm = FileManager.default let docsurl = try! fm.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) debugPrint(docsurl) guard let usdzURL = Bundle.main.url(forResource: "plantpot", withExtension: "usdz") else { fatalError("Failed to find USDZ file in bundle") } // Load the USDZ file using SceneKit guard let scene = try? SCNScene(url: usdzURL, options: [.checkConsistency: true]) else { print("Failed to load scene") return } // Create a Model I/O asset from the SceneKit scene let asset = MDLAsset(scnScene: scene) debugPrint("Count",asset.count) let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let fbxURL = documentsDirectory.appendingPathComponent(outputFileName) if FileManager.default.fileExists(atPath: fbxURL.path) { print("Output file already exists") return } if !FileManager.default.isWritableFile(atPath: fbxURL.path) { print("The file at \(fbxURL.path) exists but is not writable.") } else { print("The file at \(fbxURL.path) exists and is writable.") } do { try asset.export(to: fbxURL) print("Conversion complete. Output file: \(fbxURL.path)") } catch let error { print("Error exporting to FBX: \(error.localizedDescription)") } print("Conversion complete. Output file: \(fbxURL.path)") }
问题排查与修复点
1. 输出文件名配置错误
当前代码中outputFileName设置为"Rom3.obj",注释掉了FBX格式的文件名。要转换FBX,必须将outputFileName改为"Rom3.fbx",否则代码会生成OBJ文件而非FBX,导致后续逻辑错误。
2. 输入文件未匹配目标USDZ
代码硬编码加载了"plantpot.usdz",但你实际需要转换的是"Rom2.usdz"。需修改资源加载逻辑,使用inputFileName对应的文件:
// 拆分文件名和扩展名 let inputName = inputFileName.components(separatedBy: ".").first! let inputExt = inputFileName.components(separatedBy: ".").last! guard let usdzURL = Bundle.main.url(forResource: inputName, withExtension: inputExt) else { fatalError("Failed to find USDZ file in bundle") }
3. 文件可写性判断逻辑无效
当目标FBX文件不存在时,isWritableFile(atPath:)会返回false(因为文件尚未创建),这个判断没有实际意义,反而会输出错误提示。建议移除该判断,改为检查文档目录的可写性:
guard documentsDirectory.hasDirectoryPath, FileManager.default.isWritableFile(atPath: documentsDirectory.path) else { print("Documents directory is not writable") return }
4. MDLAsset导出FBX的格式选项
MDLAsset导出FBX时,可指定导出选项确保层级结构和数据完整性,避免因格式兼容问题导致导出失败:
let exportOptions: [MDLAssetExportOption: Any] = [ .preserveTopLevelHierarchy: true, .exportTextures: true ] try asset.export(to: fbxURL, options: exportOptions)
修正后的完整代码
let inputFileName = "Rom2.usdz" let outputFileName = "Rom3.fbx" override func viewDidLoad() { super.viewDidLoad() let fm = FileManager.default let docsurl = try! fm.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) debugPrint(docsurl) // 正确加载目标USDZ文件 let inputName = inputFileName.components(separatedBy: ".").first! let inputExt = inputFileName.components(separatedBy: ".").last! guard let usdzURL = Bundle.main.url(forResource: inputName, withExtension: inputExt) else { fatalError("Failed to find USDZ file in bundle") } // Load the USDZ file using SceneKit guard let scene = try? SCNScene(url: usdzURL, options: [.checkConsistency: true]) else { print("Failed to load scene") return } // Create a Model I/O asset from the SceneKit scene let asset = MDLAsset(scnScene: scene) debugPrint("Asset count: \(asset.count)") let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let outputURL = documentsDirectory.appendingPathComponent(outputFileName) // 检查目录可写性 guard documentsDirectory.hasDirectoryPath, FileManager.default.isWritableFile(atPath: documentsDirectory.path) else { print("Documents directory is not writable") return } // 检查文件是否已存在 if FileManager.default.fileExists(atPath: outputURL.path) { print("Output file already exists: \(outputURL.path)") return } do { // 指定FBX导出选项 let exportOptions: [MDLAssetExportOption: Any] = [ .preserveTopLevelHierarchy: true, .exportTextures: true ] try asset.export(to: outputURL, options: exportOptions) print("Conversion complete. Output file: \(outputURL.path)") } catch let error { print("Error exporting to FBX: \(error.localizedDescription)") print("Full error: \(error)") // 打印完整错误信息便于排查 } }
内容的提问来源于stack exchange,提问作者Nishant Chandwani
相关产品推荐
相关产品推荐

