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

基于ARKit的iOS应用门体点击开合手势交互实现咨询

实现ARKit门体点击旋转交互的分步指南

Hey there! 很高兴你已经搞定了自定义箱体模型的放置,接下来实现门的点击开关其实核心就是手势识别+节点动画,我给你捋个清晰的实现步骤:

1. 给门节点做标记,方便识别点击

首先要确保你的门模型节点有一个独一无二的标识,这样点击时能区分门和箱体其他部分。在加载门模型的时候,给它设置name属性:

// 假设你加载门模型后得到doorNode
doorNode.name = "interactiveDoor"
// 如果门是箱体节点的子节点,别忘了把它添加到箱体节点上
boxNode.addChildNode(doorNode)

2. 给ARView添加点击手势识别器

在你的ARViewController的viewDidLoad方法里,添加一个点击手势监听器,用来捕获用户的点击操作:

override func viewDidLoad() {
    super.viewDidLoad()
    // 其他初始化代码...
    
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoorTap(_:)))
    arView.addGestureRecognizer(tapGesture)
}

3. 处理点击事件,实现门的旋转动画

接下来编写手势处理方法,核心是通过ARView的命中测试找到被点击的门节点,然后根据当前状态执行打开/关闭的平滑动画:

// 用字典记录每个门的开关状态,key是节点的唯一ID,避免多门互相干扰
private var doorStates: [UUID: Bool] = [:]

@objc private func handleDoorTap(_ gesture: UITapGestureRecognizer) {
    // 获取点击在ARView上的位置
    let tapLocation = gesture.location(in: arView)
    
    // 执行命中测试,优先检测模型节点(这里用boundingBoxOnly确保检测到节点本身)
    guard let hitResult = arView.hitTest(tapLocation, options: [
        SCNHitTestOption.boundingBoxOnly: true,
        SCNHitTestOption.searchMode: SCNHitTestSearchMode.all.rawValue
    ]).first,
          let doorNode = hitResult.node,
          doorNode.name == "interactiveDoor" else {
        // 没点击到门,直接返回
        return
    }
    
    // 获取当前门的状态,默认是关闭(false)
    let isDoorOpen = doorStates[doorNode.id] ?? false
    
    // 计算目标旋转角度:这里假设门绕Y轴旋转90度打开,根据你的模型调整轴向和角度
    // 如果你的门是左右开,一般绕Y轴;上下开绕X轴,自己适配哦
    let targetRotation = isDoorOpen ? 
        simd_quatf(angle: 0, axis: SIMD3(x: 0, y: 1, z: 0)) : // 关闭状态
        simd_quatf(angle: -.pi/2, axis: SIMD3(x: 0, y: 1, z: 0)) // 打开状态(逆时针转90度)
    
    // 用SCNTransaction实现平滑动画
    SCNTransaction.begin()
    SCNTransaction.animationDuration = 0.5 // 动画时长0.5秒
    doorNode.simdOrientation = targetRotation
    SCNTransaction.commit()
    
    // 更新门的状态
    doorStates[doorNode.id] = !isDoorOpen
}

几个关键细节要注意

  • 模型层级适配:如果门是箱体的子节点,命中测试可能会先检测到箱体节点,这时候可以调整hitTest的选项,或者遍历hitResult的node的子节点找名字为interactiveDoor的节点。
  • 旋转轴向调整:不同建模软件导出的模型轴向可能不一样,如果你发现门旋转方向不对,试着修改axis参数(比如把SIMD3(x:0,y:1,z:0)改成SIMD3(x:1,y:0,z:0)),或者调整旋转角度的正负值。
  • 动画方式可选:除了用SCNTransaction,你也可以用SCNAction实现动画,比如:
    let rotateAction = isDoorOpen ? 
        SCNAction.rotateTo(x: 0, y: 0, z: 0, duration: 0.5) : 
        SCNAction.rotateTo(x: 0, y: -.pi/2, z: 0, duration: 0.5)
    doorNode.runAction(rotateAction)
    

这样就能实现点击门体切换开关状态的交互啦,亲测在官方“放置物体”示例基础上改完全可行~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:18:36