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

如何为Reality Composer场景中所有模型实体(含同名)添加手势?

解决RealityKit中同名实体无法批量添加手势的问题

问题核心:findEntity(named:)方法仅会返回第一个匹配名称的实体,导致场景中同名的第二个模型无法被获取,进而无法添加交互手势。

完整解决方案

通过递归遍历实体树,找出所有目标实体(无论是按名称匹配还是按类型匹配),再逐个为它们添加碰撞形状和手势。

修改后的完整代码如下:

import UIKit
import RealityKit
import SwiftUI

class ViewController: UIViewController {
    
    @IBOutlet var arView: ARView!
    typealias GstReady = Entity & HasCollision

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let boxAnchor = try! Experience.loadBox()
        arView.scene.anchors.append(boxAnchor)
        
        let cubesAnchor = try! Experience.loadCubes()
        arView.scene.anchors.append(cubesAnchor)
        
        // 递归查找所有名为"simpBld_root"的实体
        let targetEntities = findAllEntities(named: "simpBld_root", in: cubesAnchor)
        for entity in targetEntities {
            guard let gestureReadyEntity = entity as? GstReady else { continue }
            // 生成碰撞形状(若模型有子节点需碰撞,可将recursive改为true)
            gestureReadyEntity.generateCollisionShapes(recursive: false)
            // 安装所有手势
            arView.installGestures([.all], for: gestureReadyEntity)
        }
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0){
            let coneAnchor = try! Experience.loadCone()
            self.arView.scene.anchors.append(coneAnchor)
        }
    }
    
    // 递归遍历实体树,查找所有同名实体
    private func findAllEntities(named name: String, in parent: Entity) -> [Entity] {
        var matches = [Entity]()
        for child in parent.children {
            if child.name == name {
                matches.append(child)
            }
            // 递归查找子节点
            matches.append(contentsOf: findAllEntities(named: name, in: child))
        }
        return matches
    }
    
    // 可选:若要给所有符合GstReady类型的实体加手势,可使用此方法
    private func findAllGestureReadyEntities(in parent: Entity) -> [GstReady] {
        var matches = [GstReady]()
        for child in parent.children {
            if let gstEntity = child as? GstReady {
                matches.append(gstEntity)
            }
            matches.append(contentsOf: findAllGestureReadyEntities(in: child))
        }
        return matches
    }
}

关键说明

  1. 递归查找函数:findAllEntities(named:in:)会遍历父实体下的所有子实体及后代,收集所有名称匹配的实体,解决了单个findEntity只能返回第一个结果的问题。
  2. 批量处理实体:循环遍历所有找到的目标实体,逐个生成碰撞形状(RealityKit手势依赖碰撞组件)并安装交互手势。
  3. 可选的类型匹配:如果不需要按名称筛选,而是给所有符合Entity & HasCollision类型的实体加手势,可以使用findAllGestureReadyEntities(in:)方法替代。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:24:55