设置:
我正在开发一个使用沉浸式空间的visionOS应用程序。
用户看到一个板上放置了实体。
我的应用程序将板放置在默认相机和相对于板具有特定位置和方向的实体前面。放置和旋转应该是动画的。
问题:
如果我通过直接将
Transform
分配给实体的 transform
属性来放置实体,即没有动画,则结果是正确的。move(to:
函数来为其设置动画。而且 move(to:
以意想不到的方式发挥作用。直接设置
transform
(无动画)。这给出了正确的结果,并且按预期工作(没有动画)
使用
transform
相对于世界设置 move
(无动画)。这给出了正确的结果,尽管它没有按预期工作。我期望“相对于世界”意味着平移和旋转是相对于世界的。这对于平移来说似乎是错误的,对于旋转来说是正确的。
使用
transform
相对于 move
设置 parentEntity
(无动画)。尽管 translation
和 rotation
是相对于 parentEntity
定义的,但这会给出错误的结果。
使用
transform
相对于动画世界设置 move
。这也会给出错误的结果,并且没有动画。
使用
transform
相对于 move
设置 parentEntity
,并带有动画。这也会给出错误的结果,并且没有动画。
以下是案例 1...5 的屏幕截图:
问题:
所以,显然,我不明白
move(to:
的作用。我很乐意得到任何建议,什么是错的以及如何做正确的。
这是代码:
import SwiftUI
import RealityKit
import RealityKitContent
struct ImmersiveView: View {
@Environment(AppModel.self) var appModel
let boardHeight: Float = 0.1
let boxHeight: Float = 0.3
var body: some View {
RealityView { content in
let boardEntity = makeBoard()
content.add(boardEntity)
let boxEntity = makeBox(parentEntity: boardEntity)
boardEntity.addChild(boxEntity)
}
}
func makeBoard() -> ModelEntity {
let mesh = MeshResource.generateBox(width: 1.0, height: boardHeight, depth: 1.0)
var material = UnlitMaterial(); material.color.tint = .red
let boardEntity = ModelEntity(mesh: mesh, materials: [material])
boardEntity.transform.translation = [0, 0, -3]
return boardEntity
}
func makeBox(parentEntity: Entity) -> ModelEntity {
let mesh = MeshResource.generateBox(width: 0.3, height: boxHeight, depth: 0.3)
var material = UnlitMaterial(); material.color.tint = .green
let boxEntity = ModelEntity(mesh: mesh, materials: [material])
// Set position and orientation of the box
// To put the box onto the board, move it up by half height of the board and half height of the box
let y_up = boardHeight/2.0 + boxHeight/2.0
let translation = SIMD3<Float>(0, y_up, 0)
// Turn the box by 45 degrees around the y axis
let rotationY = simd_quatf(angle: Float(45.0 * .pi/180.0), axis: SIMD3(x: 0, y: 1, z: 0))
let transform = Transform(rotation: rotationY, translation: translation)
// Do the actual move
// 1) Set transform directly (without animation)
boxEntity.transform = transform // Translation and rotation correct
// 2) Set transform using move relative to world (without animation)
// boxEntity.move(to: transform, relativeTo: nil) // Translation and rotation correct
// 3) Set transform using move relative to parentEntity (without animation)
// boxEntity.move(to: transform, relativeTo: parentEntity) // Translation incorrect, rotation correct
// 4) Set transform using move relative to world with animation
// boxEntity.move(to: transform,
// relativeTo: nil,
// duration: 1.0,
// timingFunction: .linear) // Translation incorrect, rotation incorrect, no animation
// 5) Set transform using move relative to parentEntity with animation
// boxEntity.move(to: transform,
// relativeTo: parentEntity,
// duration: 1.0,
// timingFunction: .linear) // 5) Translation incorrect, rotation incorrect, no animation
return boxEntity
}
}
这似乎是一个 RealityKit 错误。
我在Apple的开发者论坛上发布了这个问题,Vision Pro工程师回答并找到了解决方法(缩写):
这可能是一个错误,但我们的团队需要进一步调查。 请考虑使用反馈助手提交错误。
我这样做了(FB15152333)。
解决方法如下:
import SwiftUI
import RealityKit
import RealityKitContent
struct ImmersiveView: View {
@Environment(AppModel.self) var appModel
let boardHeight: Float = 0.1
let boxHeight: Float = 0.3
var body: some View {
RealityView { content in
let boardEntity = makeBoard()
content.add(boardEntity)
let mesh = MeshResource.generateBox(width: 0.3, height: boxHeight, depth: 0.3)
var material = UnlitMaterial(); material.color.tint = .green
let boxEntity = ModelEntity(mesh: mesh, materials: [material])
boardEntity.addChild(boxEntity)
Task {
moveBox(boxEntity, parentEntity: boardEntity)
}
}
}
func makeBoard() -> ModelEntity {
let mesh = MeshResource.generateBox(width: 1.0, height: boardHeight, depth: 1.0)
var material = UnlitMaterial(); material.color.tint = .red
let boardEntity = ModelEntity(mesh: mesh, materials: [material])
boardEntity.transform.translation = [0, 0, -3]
return boardEntity
}
func moveBox(_ boxEntity:Entity, parentEntity: Entity) {
// Set position and orientation of the box
// To put the box onto the board, move it up by half height of the board and half height of the box
let y_up = boardHeight/2.0 + boxHeight/2.0
let translation = SIMD3<Float>(0, y_up, 0)
// Turn the box by 45 degrees around the y axis
let rotationY = simd_quatf(angle: Float(45.0 * .pi/180.0), axis: SIMD3(x: 0, y: 1, z: 0))
let transform = Transform(rotation: rotationY, translation: translation)
// Do the actual move
// 5) Set transform using move relative to parentEntity with animation
boxEntity.move(to: transform,
relativeTo: parentEntity,
duration: 1.0,
timingFunction: .linear) // 5) Translation incorrect, rotation incorrect, no animation
}
}