Godot将FBX重打包为SCN文件后骨骼绑定异常问题求助
问题原因
你当前代码出现骨骼错位、翻转的核心原因是3个坐标空间和数据同步的遗漏:
- 你只复制了原始Skeleton的骨骼名称、父级关系、rest姿势,没有同步原始Skeleton的全局变换属性。FBX导入Godot时,默认会给根节点附加适配坐标轴的转换(常见为Y轴向上适配、Z轴翻转),你新建的Skeleton直接挂在空节点下,没有带上这部分变换,导致骨骼空间和蒙皮数据的绑定空间不匹配。
- 新建Skeleton添加完骨骼数据后没有调用强制更新接口,骨骼的内部缓存数据未生效,蒙皮计算时读取到错误的骨骼位置。
- 复制MeshInstance时仅同步了mesh资源,没有同步原始MeshInstance的相对变换、表面材质属性,进一步放大了错位效果。
修复方案
你可以直接修改原有代码的Skeleton处理和MeshInstance处理部分,修复后代码如下:
func fbx_to_scn(node): var spi = Spatial.new() add_child(spi) spi.name = node node = get_node(node+"/RootNode") var ps var mesh for i in node.get_child_count(): var child = node.get_child(i) if child.get_class() == "Skeleton": ps = child elif child.get_class() == "MeshInstance": mesh = child if not ps == null: var new_sklet : Skeleton = Skeleton.new() # 同步原始Skeleton的全局变换到新节点的局部空间 new_sklet.transform = spi.get_global_transform().affine_inverse() * ps.get_global_transform() for i in ps.get_bone_count(): new_sklet.add_bone(ps.get_bone_name(i)) new_sklet.set_bone_rest(i,ps.get_bone_rest(i)) if ps.get_bone_parent(i) != -1: new_sklet.set_bone_parent(i,ps.get_bone_parent(i)) # 强制刷新骨骼内部缓存,必须在添加完所有骨骼后调用 new_sklet.force_update_all_bones() spi.add_child(new_sklet) new_sklet.owner = spi new_sklet.name = "Skeleton" var mi = MeshInstance.new() mi.name = "MeshInstance" mi.mesh = mesh.mesh # 同步原始Mesh的变换和材质属性 mi.transform = spi.get_global_transform().affine_inverse() * mesh.get_global_transform() mi.material_override = mesh.material_override for s in range(mesh.get_surface_count()): mi.set_surface_material(s, mesh.get_surface_material(s)) spi.add_child(mi) mi.owner = spi if not ps == null: mi.skeleton = "../Skeleton" var pack = PackedScene.new() pack.pack(spi) if ResourceSaver.save("res://save_file/" +spi.name+ ".scn",pack) == OK: print("file saved") else: print("some thing went wrong")
如果修改后还有轻微的轴向翻转问题,可以在FBX导入设置中关闭「自动轴转换」选项,或者给spi节点附加一个transform.basis = Basis(Vector3.UP, PI)的旋转,抵消FBX默认的坐标翻转。
内容的提问来源于stack exchange,提问作者Mori Norabadi
相关产品推荐
相关产品推荐

