检测沉浸式空间中的手势 VisionOs SwiftUI

Ari*_*ain 5 swiftui realitykit visionos

我有一个沉浸式空间,我想向其中添加手势识别器。我希望能够在沉浸式空间中的任何位置检测捏/点击手势。

ImmersiveSpace(id: "FlappyImmersiveSpace") {     
    FlappySpace() 
}
Run Code Online (Sandbox Code Playgroud)

我尝试过这个,但没有成功。

ImmersiveSpace(id: "FlappyImmersiveSpace") {
    FlappySpace()
        .gesture(
            TapGesture()
                .onEnded({ _ in
                    print("TAPPED")
                })
        )
}
Run Code Online (Sandbox Code Playgroud)

这也不行。

struct FlappySpace: View {

    var body: some View {
        RealityView { content in
            // Logic
        }
        .gesture(
            TapGesture()
                .onEnded({ _ in
                    print("TAPPED")
                })
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

有谁知道如何检测沉浸式空间中的手势,手势不能特定于空间中的实体,而是整个空间中的任何位置。特别想检测点击手势(在 VisionOS 中,这是捏)。

Ahm*_*awy 0

您需要调用空间点击手势

像这样

        .gesture(
            SpatialTapGesture()
                .targetedToEntity(entity)
                .onEnded { value in
                    print("you touch me")

                }
        )
Run Code Online (Sandbox Code Playgroud)

这是一个带有网格立方体的完整示例,您可以用手指触摸它来设置动画并跳跃,使用双击它会跳得更多

import SwiftUI
import RealityKit


struct Cube: View {
    @State var z: Float = 0.0
    @State private var subs: [EventSubscription] = []
    @State private var contentEntity = Entity()
    @State var cube1 = ModelEntity()



    var body: some View {
        RealityView { content, attachments in
            content.add(setupContentEntity())
            
            cube1 = addCube(name: "Cube1", posision: SIMD3(x: 1, y: 1, z: -2), color: .red)
            
            if let attachment = attachments.entity(for: "cube1_label") {
                attachment.position = [0, -0.35, 0]
                cube1.addChild(attachment)
            }
            
        } attachments: {
            Attachment(id: "cube1_label") {
                Text("Cube1")
                    .font(.system(size: 48))
            }
        }
        .gesture(
            SpatialTapGesture()
                .targetedToEntity(cube1)
                .onEnded { value in
                    print(value)
                   playAnimation(entity: cube1)
                }
        )
    }
    
    func setupContentEntity() -> Entity {
        return contentEntity
    }

    func getTargetEntity(name: String) -> Entity? {
        return contentEntity.children.first { $0.name == name}
    }

    func addCube(name: String, posision: SIMD3<Float>, color: UIColor) -> ModelEntity {
        let entity = ModelEntity(
            mesh: .generateBox(size: 0.5, cornerRadius: 0),
            materials: [SimpleMaterial(color: color, isMetallic: false)],
            collisionShape: .generateBox(size: SIMD3<Float>(repeating: 0.5)),
            mass: 0.0
        )

        entity.name = name
        entity.position = posision
        entity.components.set(InputTargetComponent(allowedInputTypes: .indirect))
        entity.components.set(CollisionComponent(shapes: [ShapeResource.generateBox(size: SIMD3<Float>(repeating: 0.5))], isStatic: true))
        entity.components.set(HoverEffectComponent())

        contentEntity.addChild(entity)
        
        return entity
    }

    func playAnimation(entity: Entity) {
        let goUp = FromToByAnimation<Transform>(
            name: "goUp",
            from: .init(scale: .init(repeating: 1), translation: entity.position),
            to: .init(scale: .init(repeating: 1), translation: entity.position + .init(x: 0, y: 0.4, z: 0)),
            duration: 0.2,
            timing: .easeOut,
            bindTarget: .transform
        )

        let pause = FromToByAnimation<Transform>(
            name: "pause",
            from: .init(scale: .init(repeating: 1), translation: entity.position + .init(x: 0, y: 0.4, z: 0)),
            to: .init(scale: .init(repeating: 1), translation: entity.position + .init(x: 0, y: 0.4, z: 0)),
            duration: 0.1,
            bindTarget: .transform
        )

        let goDown = FromToByAnimation<Transform>(
            name: "goDown",
            from: .init(scale: .init(repeating: 1), translation: entity.position + .init(x: 0, y: 0.4, z: 0)),
            to: .init(scale: .init(repeating: 1), translation: entity.position),
            duration: 0.2,
            timing: .easeOut,
            bindTarget: .transform
        )

        let goUpAnimation = try! AnimationResource
            .generate(with: goUp)

        let pauseAnimation = try! AnimationResource
            .generate(with: pause)

        let goDownAnimation = try! AnimationResource
            .generate(with: goDown)

        let animation = try! AnimationResource.sequence(with: [goUpAnimation, pauseAnimation, goDownAnimation])

        entity.playAnimation(animation, transitionDuration: 0.5)
    }

}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 这实际上并没有回答这个问题,即“我希望能够在沉浸式空间中的任何位置检测捏/点击手势”。您的回复提供了(一个很好的)示例,说明如何使用点击手势定位实体。我也在寻找一种在 ImmersiveSpace 上可靠地生成拖动/点击事件的方法。“点击任意位置”的一个用例可能是调出自动消失的视频播放器控件,或者在“拖动任意位置”的情况下移动整个 3D 场景。 (2认同)