在EditorImportPlugin中加载FBX文件报错,如何正确加载FBX文件?
问题描述
我正在尝试创建EditorPlugin/EditorImportPlugin来导入FBX文件,目标是从中提取动画并保存为.res文件。平时我会通过编辑器的高级导入选项卡选择动画并启用「保存到文件」功能:
我的EditorPlugin代码如下:
[Tool] public partial class FbxAnimationImportPlugin : EditorPlugin { private FbxAnimationImporter fbxAnimationImporter; public override void _EnterTree() { fbxAnimationImporter = new FbxAnimationImporter(); AddImportPlugin(fbxAnimationImporter); } public override void _ExitTree() { RemoveImportPlugin(fbxAnimationImporter); fbxAnimationImporter = null; } }
对应的EditorImportPlugin代码:
[Tool] public partial class FbxAnimationImporter : EditorImportPlugin { public override string _GetImporterName() { return "fbx_animation_importer"; } public override string _GetVisibleName() { return "FbxAnimationImporter"; } public override string[] _GetRecognizedExtensions() { return ["fbx"]; } public override string _GetSaveExtension() { return "res"; } public override string _GetResourceType() { return "PackedScene"; } public override Error _Import(string sourceFile, string savePath, Dictionary options, Array<string> platformVariants, Array<string> genFiles) { Resource scene = ResourceLoader.Load(sourceFile, "PackedScene"); //Doing stuff with the scene and animations... return Error.Ok; } }
运行时遇到以下错误:
ERROR: Failed loading resource: res://assets/protof/Humanoid@WallJumpLeft.fbx. Make sure resources have been imported by opening the project in the editor at least once.
请问如何正确将FBX文件加载为PackedScene,以便访问其中内嵌的AnimationPlayer?
解决方案
你不能直接用ResourceLoader.Load()加载原始FBX文件——Godot的ResourceLoader只能加载已经完成导入流程的资源,而原始FBX属于未导入的源文件,必须通过编辑器的导入管线处理后才能转为PackedScene。
方法1:复用内置FBX导入器
先调用Godot默认的FBX导入器完成基础导入,再从生成的PackedScene中提取动画:
public override Error _Import(string sourceFile, string savePath, Dictionary options, Array<string> platformVariants, Array<string> genFiles) { // 获取内置FBX导入器 EditorImportPlugin fbxImporter = EditorInterface.Singleton.GetImportPlugin("fbx"); if (fbxImporter == null) { return Error.Failed; } // 先让内置导入器生成临时PackedScene Error importError = fbxImporter._Import(sourceFile, savePath + "_temp", options, platformVariants, genFiles); if (importError != Error.Ok) { return importError; } // 加载临时场景 PackedScene tempScene = ResourceLoader.Load<PackedScene>(savePath + "_temp.res"); if (tempScene == null) { return Error.Failed; } // 实例化场景并获取AnimationPlayer Node rootNode = tempScene.Instantiate(); AnimationPlayer animPlayer = rootNode.GetNode<AnimationPlayer>("AnimationPlayer"); // 提取并保存动画 if (animPlayer != null && animPlayer.GetAnimationCount() > 0) { Animation targetAnim = animPlayer.GetAnimation(0); ResourceSaver.Save(targetAnim, savePath + ".res"); } // 清理临时文件与节点 DirAccess.Remove(savePath + "_temp.res"); rootNode.QueueFree(); return Error.Ok; }
方法2:直接解析FBX提取动画
如果不需要完整场景,可直接用EditorFBXImporter解析FBX获取动画,跳过场景导入步骤:
public override Error _Import(string sourceFile, string savePath, Dictionary options, Array<string> platformVariants, Array<string> genFiles) { EditorFBXImporter fbxParser = new EditorFBXImporter(); // 配置解析选项:只导入动画,关闭网格导入 Dictionary parseOpts = new Dictionary(); parseOpts["import_animations"] = true; parseOpts["import_meshes"] = false; // 解析FBX文件 Error parseErr = fbxParser.ParseFile(sourceFile, parseOpts); if (parseErr != Error.Ok) { return parseErr; } // 获取并保存动画 Array<Animation> animations = fbxParser.GetAnimations(); if (animations.Count > 0) { ResourceSaver.Save(animations[0], savePath + ".res"); } return Error.Ok; }
关键注意点
- 插件的
plugin.cfg必须声明依赖editor模块,否则无法访问EditorFBXImporter等编辑器专属API。 - 若仅提取动画,建议将
_GetResourceType()的返回值改为"Animation",更符合资源类型逻辑。 - 可通过
options参数读取用户在导入面板设置的选项(如指定要提取的动画),提升插件灵活性。
内容的提问来源于stack exchange,提问作者KilledByCheese
相关产品推荐
相关产品推荐

