Activation des gestes dans RealityKit
J'ai un fichier usdz personnalisé (pas créé par code, mais disons une vraie chaise!). Je sauvegarde ceci dans un fichier Entity.
Une fois que je l'ai, voici mon code:
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)")
}
}
Le problème ici est que `` Le type d'argument 'Entity' n'est pas conforme au type attendu 'HasCollision' ". Donc je ne peux ajouter aucun geste.
Mais je ne trouve aucune ressource utile pour atteindre mon objectif final. Y a-t-il des conseils?
Réponses
Utilisez la forme forcée de downcasting (type casting) as!avec Entity & HasCollision.
arView.installGestures([.rotation], for: modelEntity as! Entity & HasCollision)
ou de cette façon:
let entity = modelEntity as? Entity & HasCollision
arView.installGestures([.all], for: entity!)
Une méthode d'instance sourceinstallGestures(_:for:) ressemble à ceci:
@discardableResult func installGestures(_ gestures: ARView.EntityGestures = .all,
for entity: HasCollision) -> [EntityGestureRecognizer]
Paramètres initiaux dans Reality Composer
Avant la compilation, dans Reality Composer set physics = participateset motion type = fixedet accessibility = accessibility enabledpour votre modèle.
Version complète du code
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]
}
}
}
Le problème est que vous essayez de donner à ModelEntity une capacité qu'elle ne possède pas (elle n'a pas de gestionnaire de collision).
Vous devez créer vous-même une entité, qui sera conforme à HasCollision.
J'essaierais quelque chose comme ça:
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
}
J'ai eu une autre situation: j'avais besoin de charger le modèle à partir d'un .usdzfichier et il devrait avoir une animation. Mais aussi j'avais besoin d'avoir des gestes comme la translation et la rotation. La recherche m'a orienté vers le fil avec la bonne réponse. Le code que je vais montrer ci-dessous, l'idée principale est "d'imbriquer l'entité chargée qui contient les animations à l'intérieur d'un ModelEntity, puis de donner à ce ModelEntity un CollisionComponent approprié basé sur les limites du modèle chargé." (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)
}