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

如何用SK3DNode在SpriteKit项目中展示.usdz模型并实现旋转缩放?

在SpriteKit中集成3D模型并实现旋转缩放功能

核心方案:使用SK3DNode嵌入SceneKit内容

SpriteKit提供了SK3DNode类,专门用来在2D场景中嵌入3D内容,你可以借助它复用SceneKit的模型加载和变换能力,轻松实现旋转、缩放需求。

1. 加载3D模型到SCNScene

先通过SceneKit加载你的3D模型文件(支持.dae、.scn、.usdz等格式):

// 加载本地模型文件,替换成你的模型名称和格式
guard let sceneURL = Bundle.main.url(forResource: "PlayerModel", withExtension: "dae") else {
    fatalError("模型文件未找到")
}
let scnScene = try! SCNScene(url: sceneURL)

2. 创建SK3DNode并添加到SpriteKit场景

将SCNScene关联到SK3DNode,再把这个节点加入SpriteKit场景:

// 设置3D视图的显示尺寸,可根据需求调整
let sk3DNode = SK3DNode(viewportSize: CGSize(width: 400, height: 400))
sk3DNode.scnScene = scnScene
// 将节点放置在屏幕中心
sk3DNode.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
self.addChild(sk3DNode)

3. 实现旋转功能

有两种方式控制旋转,按需选择:

  • 方式一:旋转SK3DNode(整体视角旋转)
// 在update方法中实现自动旋转
override func update(_ currentTime: TimeInterval) {
    sk3DNode.eulerAngles.y += 0.01 // 绕Y轴缓慢旋转
}
  • 方式二:旋转模型本身的SCNNode(精准控制模型)
// 获取模型根节点(根据你的模型结构调整节点获取逻辑)
guard let modelNode = scnScene.rootNode.childNodes.first else { return }
// 绕X轴旋转
modelNode.eulerAngles.x += 0.01

4. 实现缩放功能

同样支持两种缩放方式:

  • 缩放SK3DNode(整体缩放)
sk3DNode.setScale(1.2) // 放大到1.2倍
  • 缩放模型的SCNNode
modelNode.scale = SCNVector3(0.7, 0.7, 0.7) // 缩小到0.7倍

5. 触摸交互控制旋转缩放(可选)

如果需要通过触摸手动控制,添加以下代码:

var lastTouchPos: CGPoint = .zero

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    lastTouchPos = touch.location(in: self)
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    let currentPos = touch.location(in: self)
    let deltaX = currentPos.x - lastTouchPos.x
    let deltaY = currentPos.y - lastTouchPos.y
    
    // 单指拖动旋转模型
    guard let modelNode = scnScene.rootNode.childNodes.first else { return }
    modelNode.eulerAngles.y += deltaX * 0.01
    modelNode.eulerAngles.x += deltaY * 0.01
    
    lastTouchPos = currentPos
}

// 双指缩放
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    if touches.count == 2 {
        let touchesArr = Array(touches)
        let prevDist = distance(touchesArr[0].previousLocation(in: self), touchesArr[1].previousLocation(in: self))
        let currDist = distance(touchesArr[0].location(in: self), touchesArr[1].location(in: self))
        let scaleRatio = currDist / prevDist
        
        guard let modelNode = scnScene.rootNode.childNodes.first else { return }
        modelNode.scale *= Float(scaleRatio)
    }
}

private func distance(_ p1: CGPoint, _ p2: CGPoint) -> CGFloat {
    let dx = p1.x - p2.x
    let dy = p1.y - p2.y
    return sqrt(dx*dx + dy*dy)
}

注意事项

  • 确保模型文件已正确添加到项目,并勾选对应的target
  • 如果模型显示异常,可自定义相机调整视角:
let camera = SCNCamera()
camera.zNear = 0.1
camera.zFar = 1000
let cameraNode = SCNNode()
cameraNode.camera = camera
cameraNode.position = SCNVector3(x: 0, y: 0, z: 6) // 调整相机与模型的距离
scnScene.rootNode.addChildNode(cameraNode)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 04:00:16