Włączanie gestów w RealityKit
Mam niestandardowy plik usdz (nie tworzę za pomocą kodu, ale powiedzmy, że prawdziwe krzesło!). Zapisuję to w pliku Entity.
Kiedy już to mam, to jest mój kod:
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)")
}
}
Problem polega na tym, że „„ Typ argumentu 'Entity' nie jest zgodny z oczekiwanym typem 'HasCollision' ”. Więc nie mogę dodać żadnego gestu.
Ale nie mogę znaleźć żadnego użytecznego źródła, aby osiągnąć mój ostateczny cel. Czy jest jakaś rada?
Odpowiedzi
Użyj wymuszonej formy downcastingu (odlewania typu) as!z Entity & HasCollision.
arView.installGestures([.rotation], for: modelEntity as! Entity & HasCollision)
lub w ten sposób:
let entity = modelEntity as? Entity & HasCollision
arView.installGestures([.all], for: entity!)
Źródło metoda instancji installGestures(_:for:)wygląda następująco:
@discardableResult func installGestures(_ gestures: ARView.EntityGestures = .all,
for entity: HasCollision) -> [EntityGestureRecognizer]
Ustawienia początkowe w programie Reality Composer
Przed kompilacją, to w rzeczywistości zbiór Kompozytor physics = participatesi motion type = fixedi accessibility = accessibility enableddla danego modelu.
Pełna wersja kodu
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]
}
}
}
Problem polega na tym, że próbujesz nadać ModelEntity zdolność, której nie posiada (nie ma ona obsługi kolizji).
Musisz samodzielnie stworzyć jednostkę, która będzie zgodna z HasCollision.
Spróbowałbym czegoś takiego:
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
}
Mam inną sytuację: musiałem wczytać model z .usdzpliku i powinien mieć animację. Ale potrzebowałem też gestów, takich jak tłumaczenie i rotacja. Badania skierowały mnie do wątku z właściwą odpowiedzią. Jego kod, który pokażę poniżej, głównym pomysłem jest „zagnieżdżenie załadowanej jednostki, która ma animacje wewnątrz elementu ModelEntity, a następnie nadanie temu ModelEntity odpowiedniego składnika CollisionComponent w oparciu o granice załadowanego modelu”. (do)
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)
}