Mengaktifkan gerakan di RealityKit

Oct 03 2020

Saya memiliki file usdz khusus (bukan membuat melalui kode, tetapi katakanlah kursi sungguhan!). Saya menyimpan ini di Entity.

Setelah saya memilikinya, ini adalah kode saya:

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

Masalahnya di sini adalah bahwa "" Jenis argumen 'Entitas' tidak sesuai dengan jenis 'HasCollision' yang diharapkan ". Jadi saya tidak bisa menambahkan isyarat apapun.

Tetapi saya tidak dapat menemukan sumber daya yang berguna untuk mencapai tujuan akhir saya. Apakah ada nasihat?

Jawaban

2 AndyFedoroff Oct 03 2020 at 23:25

Gunakan bentuk paksa downcasting (tipe casting) as!dengan Entity & HasCollision.

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

atau begini:

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


Sebuah sumber metode contoh installGestures(_:for:)terlihat seperti ini:

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


Pengaturan Awal di Reality Composer

Sebelum kompilasi, di set Komposer Realitas physics = participatesdan motion type = fixeddan accessibility = accessibility enableduntuk model Anda.

Versi kode lengkap

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

Masalahnya adalah Anda mencoba memberi ModelEntity kemampuan yang tidak dimilikinya (Tidak memiliki penangan tabrakan).

Anda perlu membuat Entitas sendiri, yang akan sesuai dengan HasCollision.

Saya akan mencoba sesuatu seperti ini:

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

Saya mendapat beberapa situasi lain: Saya perlu memuat model dari .usdzfile dan itu harus memiliki animasi. Tetapi saya juga perlu memiliki gerakan seperti terjemahan dan rotasi. Penelitian itu mengarahkan saya ke utas dengan jawaban yang benar. Kode darinya akan saya tunjukkan di bawah, ide utamanya adalah "untuk menyarangkan entitas yang dimuat yang memiliki animasi di dalam ModelEntity, dan kemudian memberi ModelEntity itu CollisionComponent yang sesuai berdasarkan batas model yang dimuat." (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)
           
        }