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

如何用RealityKit编程控制Reality Composer行为?SwiftUI按钮隐藏模型

问题:SwiftUI按钮控制Reality Composer模型隐藏

我想用SwiftUI创建一个按钮,点击后隐藏Reality Composer里的模型。已经看过苹果官方教程《Creating a Trigger》,但还是搞不懂怎么通过代码控制Reality Composer的行为。

以下是我的代码:

struct VocabView : View {
    
    @State private var arView = ARView(frame: .zero)

    var body: some View {
        ZStack{
            ARViewContainer(arView: $arView)
                .ignoresSafeArea()
            VStack {
                Button("hide") {
                    hide()
                }    
            }
        }
    }
    
    func hide() {
        let demoScene = try! Experience1.loadDemo()
        if arView.scene.anchors.count > 0 {
            if arView.scene.anchors[0].isAnchored {
                demoScene.notifications.hide.post()
            }
        }
    }
}

struct ARViewContainer2: UIViewRepresentable {
    
    @Binding var arView: ARView
    
    func makeUIView(context: Context) -> ARView {
        
        let demoScene = try! Experience1.loadDemo()

        DispatchQueue.main.async {
            arView.scene.anchors.append(demoScene)
        }
        
        return arView
        
    } 
}

Reality Composer配置:
Reality Composer中配置了名为hide的通知,绑定到模型的隐藏行为


问题根源

你当前代码的核心问题是在hide()方法里重新加载了一个新的demoScene实例,而不是操作已经添加到ARView里的那个场景实例。新实例的通知和ARView中已加载的场景完全无关,所以发送通知不会有任何效果。

修复方案

  1. 保存已加载的场景实例:在视图容器中把加载好的demoScene保存下来,直接在主视图中管理,避免重复加载。
  2. 直接操作已存在的场景实例:调用已添加到ARView的场景的通知,而非新创建的实例。

修改后的代码:

struct VocabView : View {
    // 直接管理场景实例,避免重复加载
    @State private var demoScene: Experience1.Demo?
    @State private var arView = ARView(frame: .zero)

    var body: some View {
        ZStack{
            ARViewContainer(arView: $arView, demoScene: $demoScene)
                .ignoresSafeArea()
            VStack {
                Button("hide") {
                    hideModel()
                }    
            }
        }
    }
    
    func hideModel() {
        // 直接使用已加载的场景实例发送通知
        demoScene?.notifications.hide.post()
    }
}

struct ARViewContainer: UIViewRepresentable {
    @Binding var arView: ARView
    @Binding var demoScene: Experience1.Demo?
    
    func makeUIView(context: Context) -> ARView {
        // 加载一次场景并保存实例
        let scene = try! Experience1.loadDemo()
        demoScene = scene
        arView.scene.anchors.append(scene)
        return arView
    }
    
    // 必须实现updateUIView方法(UIViewRepresentable协议要求)
    func updateUIView(_ uiView: ARView, context: Context) {}
}

额外说明

  • 实际开发中避免使用try!,建议用do-catch处理场景加载可能出现的错误,防止崩溃。
  • 如果你的Reality Composer里是给模型绑定了“隐藏”行为,也可以直接通过场景实例找到模型节点,直接修改属性:
    // 假设模型在Reality Composer里的名称是"Model"
    demoScene?.children.first(where: { $0.name == "Model" })?.isHidden = true
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 06:35:16