Bật cử chỉ trong RealityKit

Oct 03 2020

Tôi có một tệp usdz tùy chỉnh (không phải tạo thông qua mã, nhưng giả sử một chiếc ghế thực sự!). Tôi lưu điều này trong a Entity.

Sau khi tôi có nó, đây là mã của tôi:

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)")
        
    }
}

Vấn đề ở đây là `` Loại đối số 'Thực thể' không phù hợp với loại 'HasCollision' được mong đợi. Vì vậy, tôi không thể thêm bất kỳ cử chỉ nào.

Nhưng tôi không thể tìm thấy bất kỳ nguồn hữu ích nào để đạt được mục tiêu cuối cùng của mình. Có lời khuyên nào không?

Trả lời

2 AndyFedoroff Oct 03 2020 at 23:25

Sử dụng hình thức bắt buộc của dự báo xuống (kiểu đúc) as!với Entity & HasCollision.

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

hoặc theo cách này:

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


Một nguồn phương pháp dụ installGestures(_:for:)trông như thế này:

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


Cài đặt ban đầu trong Reality Composer

Trước khi soạn thảo, trong thực tế Composer bộ physics = participatesvà motion type = fixedvà accessibility = accessibility enabledcho mô hình của bạn.

Phiên bản mã đầy đủ

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]
        }
    }
}
1 YanivH Oct 04 2020 at 17:30

Vấn đề là bạn đang cố gắng cung cấp cho ModelEntity một khả năng mà nó không có (Nó không có trình xử lý va chạm).

Bạn cần tự tạo một Thực thể, thực thể đó sẽ tuân theo HasCollision.

Tôi sẽ thử một cái gì đó như thế này:

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
}
АлександрГрабовский Oct 30 2020 at 00:07

Tôi gặp một số tình huống khác: Tôi cần tải mô hình từ .usdztệp và nó phải có hoạt ảnh. Nhưng tôi cũng cần phải có các cử chỉ như dịch và xoay. Nghiên cứu đã hướng tôi đến chủ đề với câu trả lời đúng. Đoạn mã từ nó mà tôi sẽ trình bày bên dưới, ý tưởng chính là "lồng thực thể được tải có các hoạt ảnh bên trong ModelEntity và sau đó cung cấp cho ModelEntity đó một CollisionComponent thích hợp dựa trên giới hạn của mô hình được tải." (c)

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)
           
        }