我有一个自定义的 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’”。所以我无法添加任何手势。
但是我找不到任何有用的资源来实现我的最终目标。有什么建议吗?
我遇到了其他情况:我需要从
.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)
}
使用强制形式的向下转换(类型转换)
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 中为您的模型设置
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 手势结合使用。
问题在于您试图赋予 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
}
启用物理 -> 参与 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)
}