在 RealityKit 中启用手势

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

我有一个自定义的 usdz 文件(不是通过代码创建的,而是一把真正的椅子!)。我将其保存在

Entity
中。

一旦我有了它,这就是我的代码:

func updateUIView(_ uiView: ARView, context: Context) {
            
    if let modelEntity = model.modelEntity {
        
        print("\(model.modelName)")
        
        let anchorEntity = AnchorEntity(plane: .horizontal)
        
        anchorEntity.addChild(modelEntity.clone(recursive: true))
        
        uiView.scene.addAnchor(anchorEntity)
        
        // modelEntity.generateCollisionShapes(recursive: true) 
        // If we have multiple object, recursive true help to generate collision for all of them
        
        uiView.installGestures(.rotation, for: modelEntity as! Entity & HasCollision)
        
        uiView.debugOptions = .showPhysics
        
    } else {
        
        print("Unable to load modelEntity for \(model.modelName)")
        
    }
}

这里的问题是“参数类型‘Entity’不符合预期类型‘HasCollision’”。所以我无法添加任何手势。

但是我找不到任何有用的资源来实现我的最终目标。有什么建议吗?

swift swiftui augmented-reality arkit realitykit
4个回答
9
投票

我遇到了其他情况:我需要从

.usdz
文件加载模型,并且它应该有动画。但我还需要平移和旋转等手势。这项研究将我引向了带有正确答案的thread。我将在下面展示其中的代码,主要思想是“将具有动画的加载实体嵌套在 ModelEntity 中,然后根据加载模型的边界为该 ModelEntity 提供适当的 CollisionComponent ”。 (三)

loadRequest = Entity.loadAsync(contentsOf: url)
    .sink(receiveCompletion: { status in
        print(status)
    }) { entity in
           
        // Scaling entity to a reasonable size
        entity.setScale(SIMD3(repeating: 0.01), relativeTo: nil)
           
        // Creating parent ModelEntity
        let parentEntity = ModelEntity()
        parentEntity.addChild(entity)
           
        // Anchoring the entity and adding it to the scene
        let anchor = AnchorEntity(.plane(.horizontal, classification: .any, minimumBounds: .zero))
        anchor.addChild(parentEntity)
        self.arView.scene.addAnchor(anchor)
           
        // Playing availableAnimations on repeat
        entity.availableAnimations.forEach { entity.playAnimation($0.repeat()) }
           
        // Add a collision component to the parentEntity with a rough shape and appropriate offset for the model that it contains
        let entityBounds = entity.visualBounds(relativeTo: parentEntity)
        parentEntity.collision = CollisionComponent(shapes: [ShapeResource.generateBox(size: entityBounds.extents).offsetBy(translation: entityBounds.center)])
                       
        // installing gestures for the parentEntity
        self.arView.installGestures(for: parentEntity)
    }

3
投票

使用强制形式的向下转换(类型转换)

as!
Entity & HasCollision

arView.installGestures([.rotation], for: modelEntity as! Entity & HasCollision)

或者这样:

let entity = modelEntity as? Entity & HasCollision
arView.installGestures([.all], for: entity!)


A source实例方法

installGestures(_:for:)
看起来像这样:

func installGestures(_ gestures: ARView.EntityGestures = .all,
                     for entity: HasCollision) -> [EntityGestureRecognizer]


Reality Composer 中的初始设置

编译之前,在 Reality Composer 中为您的模型设置

physics = participates
motion type = fixed
accessibility = accessibility enabled

完整代码版本

import SwiftUI
import RealityKit

struct ARViewContainer: UIViewRepresentable {
    
    let boxAnchor = try! Experience.loadBox()
    
    func makeUIView(context: Context) -> ARView {
        
        let arView = ARView(frame: .zero)   
        arView.scene.anchors.append(boxAnchor)
        return arView
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {
        
        if let modelEntity: Entity = boxAnchor.steelBox {    
            let anchorEntity = AnchorEntity(.plane(.vertical, 
                                             classification: .wall, 
                                             minimumBounds: [0.2, 0.2]))  
            anchorEntity.addChild(modelEntity.clone(recursive: true))    
            uiView.scene.addAnchor(anchorEntity)    
            modelEntity.generateCollisionShapes(recursive: true)    
            uiView.installGestures([.all], 
                               for: modelEntity as! Entity & HasCollision)    
            uiView.debugOptions = [.showPhysics]
        }
    }
}

P。 S.

此外,这篇文章将向您展示光线投射如何与 RealityKit 手势结合使用。


1
投票

问题在于您试图赋予 ModelEntity 一种它不具备的能力(它没有碰撞处理程序)。

您需要自己创建一个符合 HasCollision 的实体。

我会尝试这样的事情:

import RealityKit

class MyEntity: Entity, HasAnchoring, HasModel, HasCollision {

}

func updateUIView(_ uiView: ARView, context: Context) {
    // This is simply to create a dummy modelEntity
    let plane = MeshResource.generatePlane(width: 0.1, depth: 0.1)
    let texture = MaterialColorParameter.color(UIColor.red)
    var material = SimpleMaterial()
    material.baseColor = texture
    let modelEntity = ModelEntity(mesh: plane, materials: [material])
      
    // This is the class we have wrapping the model
    let myEntity = MyEntity()
    myEntity.addChild(modelEntity)
    
    // Now, we add the collision component
    let boxShape = ShapeResource.generateBox(width: 0.1, height: 0.1, depth: 0.1)
    let boxShapeCollisionComponent = CollisionComponent (
      shapes: [boxShape],
      mode: .trigger,
      filter: .default
    )
    myEntity.collision = boxShapeCollisionComponent
    // Or, you could of called myEntity.generateCollisionShapes(recursive: true)
    
    // Last thing, lets put this plane, with a box collision component,
    // right in front of us
    myEntity.transform = Transform.identity
    myEntity.transform.translation.z = myEntity.transform.translation.z - 0.3
    uiView.scene.addAnchor(myEntity)
    
    uiView.installGestures(.rotation, for: myEntity)
    
    uiView.debugOptions = .showPhysics
}

0
投票

启用物理 -> 参与 Reality Composer 中的实体并在 installGestures 之前添加

anchor.entity?.generateCollisionShapes(recursive: true)

我的例子:

Experience.loadPizzaAsync { result in
    guard case let .success(pizzaAnchor) = result
    else { return }
    
    arView.scene.addAnchor(pizzaAnchor)
    
    pizzaAnchor.pizza?.generateCollisionShapes(recursive: true)
    arView.installGestures([.rotation, .translation], for: pizzaAnchor.pizza as! HasCollision)
}
© www.soinside.com 2019 - 2024. All rights reserved.