在之前的学习中咱们在空间中增加了3D模型,但在初始摆放后就无法再对其进行移动或做出修正。本节咱们在Day 5显现和躲藏的基础上让咱们模型可以完结拖拽作用,一起对纯色的立方体完结点击随机换色的功用。
首先是进口文件,无需做出改变,
import SwiftUI
@main
struct visionOSDemoApp: App {
var body: some Scene {
WindowGroup() {
ContentView()
}
ImmersiveSpace(id: "ImmersiveSpace") {
ImmersiveView()
}
}
}
接着是ViewModel.swift
文件,这儿是中心逻辑:
import SwiftUI
import RealityKit
class ViewModel: ObservableObject {
private var contentEntity = Entity()
private let colors: [SimpleMaterial.Color] = [.gray, .red, .orange, .yellow, .green, .blue, .purple, .systemPink]
func setupContentEntity() -> Entity {
return contentEntity
}
func addCube() -> Entity {
let entity = ModelEntity(
mesh: .generateBox(size: 0.5, cornerRadius: 0),
materials: [SimpleMaterial(color: .red, isMetallic: false)],
collisionShape: .generateBox(size: SIMD3<Float>(repeating: 0.5)),
mass: 0.0
)
entity.components.set(InputTargetComponent(allowedInputTypes: .indirect))
entity.position = SIMD3(x: 0, y: 1, z: -2)
contentEntity.addChild(entity)
return entity
}
func changeToRandomColor(entity: Entity) {
guard let _entity = entity as? ModelEntity else { return }
_entity.model?.materials = [SimpleMaterial(color: colors.randomElement()!, isMetallic: false)]
}
}
这儿增加了一个colors
常量,用于设置一个包含多种色彩数组,以便进行随机色彩修正。色彩是经过SimpleMaterial
的color
参数进行随机替换(randomElement
),然后赋值给.materials
属性,这部分逻辑坐落changeToRandomColor
中。
在addCube
的逻辑中,咱们还是常规地生成一个entity
并返回。
接着来到ImmersiveView
:
import SwiftUI
import RealityKit
struct ImmersiveView: View {
@State var model = ViewModel()
@State var cube = Entity()
var body: some View {
RealityView { content in
content.add(model.setupContentEntity())
cube = model.addCube()
}
.gesture(
DragGesture()
.targetedToEntity(cube)
.onChanged { value in
cube.position = value.convert(value.location3D, from: .local, to: cube.parent!)
}
)
.gesture(
SpatialTapGesture()
.targetedToEntity(cube)
.onEnded { value in
model.changeToRandomColor(entity: cube)
}
)
}
}
在这个视图中咱们声明晰cube
变量,以便后续的拖拽和随机色彩修正操作。所以在初始化视图时将增加的立方体赋值给cube
。然后分别经过DragGesture
和SpatialTapGesture
来完结拖拽和点击的逻辑。
这儿需要说明一个本例中生成的立方体在完结拖放,躲藏后再次打开后会生成一个新的供拖放和修正色彩的模型,这时老的模型就无法再进行拖放了。假如读者只期望操作同一个模型,可以对addCube
增加了一个name
参数,并增加一个getTargetEntity
方法来获取该对象,当然也可以经过预设名称来切换不同的模型进行操作,示例修正如下:
func getTargeEntity(name: String) -> Entity? {
return contentEntity.children.first { $0.name == name }
}
func addCube(name: String) -> Entity {
if let entity = getTargeEntity(name: name) {
return entity
}
...
entity.name = name
...
对应的ImmersiveView
也要修正为类似cube = model.addCube("Cube1")
。
ContentView.swift
的代码与Day 5共同:
import SwiftUI
import RealityKit
struct ContentView: View {
@State var showImmsersiveSpace = false
@Environment(.openImmersiveSpace) var openImmersiveSpace
@Environment(.dismissImmersiveSpace) var dismissImmersiveSpace
var body: some View {
NavigationStack {
VStack {
Toggle("Show ImmersiveSpace", isOn: $showImmsersiveSpace)
.toggleStyle(.button)
}
.padding()
}
.onChange(of: showImmsersiveSpace) { _, newValue in
Task {
if newValue {
await openImmersiveSpace(id: "ImmersiveSpace")
} else {
await dismissImmersiveSpace()
}
}
}
}
}
运行使用点击盒子会随机改变色彩,拖拽盒子会跟从鼠标的方位移动。

示例代码:GitHub仓库
其它相关内容请见虚拟现实(VR)/增强现实(AR)&visionOS开发学习笔记