如何防止实体在 RealityView 中的 VisionOS Znear 中隐藏附件 SwiftUI 按钮

问题描述 投票:0回答:1

我有一个具有沉浸式空间视图的应用程序,它需要用户在底部有一个按钮,该按钮在用户头部前面有一个固定位置,就像游戏中的仪表板等,但是当用户太靠近任何 3d 时视图中的对象可能会覆盖按钮并使其无法访问,这主要会阻止应用程序获得批准,就像我之前在 SceneKit 上工作的 appstoreconnect 中一样,有一些像相机视图 Znear 和 Zfar 之类的东西决定何时隐藏 3d模型是否太近或太远,我想知道在 realityView / RealityKit 4 中是否有类似的东西。这是我的代码,屏幕截图如下

import SwiftUI

import RealityKit

struct ContentView: View {

@State var myHead: Entity = {
    let headAnchor = AnchorEntity(.head)
    headAnchor.position = [-0.02, -0.023, -0.24]
    return headAnchor
}()

@State var clicked = false

var body: some View {
    RealityView { content, attachments in
        // create a 3d box
        let mainBox = ModelEntity(mesh: .generateBox(size: [0.1, 0.1, 0.1]))
        mainBox.position = [0, 1.6, -0.3]
        
        content.add(mainBox)
        
        content.add(myHead)
        guard let attachmentEntity = attachments.entity(for: "Dashboard") else {return}
        
        myHead.addChild(attachmentEntity)

    }
    attachments: {
        // SwiftUI Inside Immersivre View
        Attachment(id: "Dashboard") {
            VStack {
                Spacer()
                    .frame(height: 300)
                Button(action: {
                    goClicked()
                }) {
                    Text(clicked ? "⏸️" : "▶️")
                        .frame(maxWidth: 48, maxHeight: 48, alignment: .center)
                        .font(.extraLargeTitle)
                }
                .buttonStyle(.plain)
            }
        }
    }
}

func goClicked() {
    clicked.toggle()
}
}

enter image description here

enter image description here

xcode swiftui realitykit visionos
1个回答
0
投票

感谢 Apple Pro Engineer,他们提供了非常有用的答案

目前无法渲染现实视图附件,例如 它总是出现在场景中其他 3D 模型的前面。

但他们也提供了一个有用的解决方法

import SwiftUI
import RealityKit

struct ContentView: View {

@State var myHead: Entity = {
    let headAnchor = AnchorEntity(.head)
    headAnchor.position = [0, -0.15, -0.4]
    return headAnchor
}()

// Use a model entity to act as a "dashboard" instead of an attachment.
@State var dashboardEntity: ModelEntity = {
    let dashboardEntity = ModelEntity(mesh: .generateSphere(radius: 0.02), materials: [])
    dashboardEntity.generateCollisionShapes(recursive: false)
    dashboardEntity.components.set(InputTargetComponent())
    return dashboardEntity
}()

@State var clicked = false

var clickedMaterial = SimpleMaterial(color: .green, isMetallic: false)

var unclickedMaterial = SimpleMaterial(color: .red, isMetallic: false)

var body: some View {
    
    RealityView { content in
        // create a 3d box
        let mainBox = ModelEntity(mesh: .generateBox(size: [0.1, 0.1, 0.1]), materials: [SimpleMaterial()])
        mainBox.position = [0, 1.6, -0.3]
        
        content.add(mainBox)
        
        content.add(myHead)
        myHead.addChild(dashboardEntity)

        // Create a model sort group for both entities.
        let group = ModelSortGroup(depthPass: .postPass)
        // Sort the box entity so that it is drawn first.
        let mainBoxSortComponent = ModelSortGroupComponent(group: group, order: 1)
        mainBox.components.set(mainBoxSortComponent)
        // Sort the dashboard entity so that it is drawn second, on top of the box.
        let dashboardSortComponent = ModelSortGroupComponent(group: group, order: 2)
        dashboardEntity.components.set(dashboardSortComponent)
    }
    update: { content in
        // Update the dashboard entity's material when the value of `clicked` changes.
        dashboardEntity.model?.materials = clicked ? [clickedMaterial] : [unclickedMaterial]
    }
    .gesture(
        TapGesture()
            .targetedToEntity(dashboardEntity)
            .onEnded({ value in
                // Toggle `clicked` when the dashboard entity is tapped.
                clicked.toggle()
            })
        )
 }
}
© www.soinside.com 2019 - 2024. All rights reserved.