You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用SCNSkinner为SceneKit合并后的自定义几何体添加Blender绑定并驱动动画

问题解答

结论

可以通过SCNSkinner将Blender导出的骨骼绑定附加到合并后的model节点上,实现对几何体的骨骼操控。

具体实现步骤

  • 第一步:导出并加载骨骼资源
    从Blender中将骨骼rig单独导出为DAE/USDZ格式,导出时仅勾选骨骼层级,不导出网格资源。将导出的骨骼文件导入Xcode项目后,加载得到骨骼根节点:
    // 加载骨骼场景
    guard let rigScene = SCNScene(named: "yourRigFile.dae"),
          let skeletonRoot = rigScene.rootNode.childNode(withName: "skeleton", recursively: true) else {
        fatalError("骨骼资源加载失败")
    }
    
    注意替换代码中的文件名、骨骼根节点名称为你Blender导出时对应的实际名称。
  • 第二步:确认顶点权重数据正常
    你在Blender中需要提前给head、upperBody、legs等各个部位的网格,针对这套rig完成顶点权重绘制,再导出单个部件导入SceneKit。调用flattenedClone()合并后,得到的model.geometry会自动整合所有子网格的boneWeights(骨骼权重)和boneIndices(骨骼索引)数据,无需额外处理。
  • 第三步:收集骨骼数据构建SCNSkinner
    先递归收集所有骨骼节点,再创建SCNSkinner实例:
    // 递归收集所有骨骼节点
    func collectBones(from node: SCNNode, into array: inout [SCNNode]) {
        if node.bone != nil {
            array.append(node)
        }
        node.childNodes.forEach { collectBones(from: $0, into: &array) }
    }
    var bones = [SCNNode]()
    collectBones(from: skeletonRoot, into: &bones)
    // 获取所有骨骼的逆绑定姿势矩阵
    let inverseBindTransforms = bones.map { $0.bone!.inverseBindTransform }
    // 创建SCNSkinner
    guard let geometry = model.geometry,
          let weightSource = geometry.sources(for: .boneWeights).first,
          let indexSource = geometry.sources(for: .boneIndices).first,
          let skinner = SCNSkinner(
              baseGeometry: geometry,
              bones: bones,
              boneInverseBindTransforms: inverseBindTransforms as [NSValue],
              boneWeights: weightSource,
              boneIndices: indexSource
          ) else {
        fatalError("SCNSkinner创建失败")
    }
    
  • 第四步:绑定到model节点
    将skinner附加到model,同时把骨骼根节点加入场景,不需要显示骨骼可设为隐藏:
    skinner.skeleton = skeletonRoot
    model.skinner = skinner
    model.addChildNode(skeletonRoot)
    // 隐藏骨骼线框
    skeletonRoot.isHidden = true
    
  • 第五步:测试骨骼操控
    修改任意骨骼的变换属性即可控制网格变形,示例:
    // 旋转第一根骨骼测试效果
    bones.first?.eulerAngles.x = .pi / 4
    

注意事项

  • 从Blender导出骨骼和各个部位网格时,必须保证两者的坐标系、原点位置、初始姿态完全一致,否则会出现网格错位问题
  • 调用flattenedClone()合并前,不要修改head、upperBody、legs等节点的初始位置、缩放、旋转参数,保持和Blender中初始姿态一致,避免权重匹配出错
  • SceneKit默认每个顶点最多受4根骨骼影响,Blender导出权重时需要对应设置权重限制

内容的提问来源于stack exchange,提问作者schnabler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 03:36:02