如何通过键盘修改并实时更新RealityKit中的Text文本
在RealityKit中实现AR文本与SwiftUI视图实时同步的问题解决
问题描述
之前在SceneKit中可以通过键盘输入实时更新AR场景中的文本,但切换到RealityKit后遇到了问题:当前SwiftUI代码能在初始化时同步HeaderView和ARView的文本内容,但修改HeaderView的文本后,ARView中的文本无法实时更新。
SceneKit可行方案代码
import SwiftUI import SceneKit struct SceneKitARView: UIViewRepresentable { @Binding var text: String func makeUIView(context: Context) -> SCNView { let scnView = SCNView() scnView.scene = SCNScene() scnView.allowsCameraControl = true // 创建文本节点 let textNode = SCNText(string: text, extrusionDepth: 0.1) let material = SCNMaterial() material.diffuse.contents = UIColor.red textNode.materials = [material] let node = SCNNode(geometry: textNode) node.position = SCNVector3(0, 0, -2) scnView.scene?.rootNode.addChildNode(node) context.coordinator.textNode = textNode return scnView } func updateUIView(_ uiView: SCNView, context: Context) { // 实时更新文本内容 context.coordinator.textNode?.string = text } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject { var parent: SceneKitARView var textNode: SCNText? init(_ parent: SceneKitARView) { self.parent = parent } } } struct HeaderView: View { @Binding var text: String var body: some View { TextField("输入文本", text: $text) .padding() .background(Color.white) } } struct SceneKitARContainer: View { @State private var text = "初始文本" var body: some View { VStack { HeaderView(text: $text) SceneKitARView(text: $text) } } }
当前RealityKit问题代码
import SwiftUI import RealityKit struct RealityKitARView: UIViewRepresentable { @Binding var text: String func makeUIView(context: Context) -> ARView { let arView = ARView(frame: .zero) let anchor = AnchorEntity(plane: .horizontal) // 创建文本实体 let textMesh = MeshResource.generateText(text, extrusionDepth: 0.01) let textMaterial = SimpleMaterial(color: .red, isMetallic: false) let textEntity = ModelEntity(mesh: textMesh, materials: [textMaterial]) textEntity.position = SIMD3<Float>(0, 0.1, 0) anchor.addChild(textEntity) arView.scene.addAnchor(anchor) context.coordinator.textEntity = textEntity return arView } func updateUIView(_ uiView: ARView, context: Context) { // 此处尝试更新文本,但无效果 guard let textEntity = context.coordinator.textEntity else { return } // 错误尝试:直接修改mesh不会触发更新 textEntity.mesh = MeshResource.generateText(text, extrusionDepth: 0.01) } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject { var parent: RealityKitARView var textEntity: ModelEntity? init(_ parent: RealityKitARView) { self.parent = parent } } } struct HeaderView: View { @Binding var text: String var body: some View { TextField("输入文本", text: $text) .padding() .background(Color.white) } } struct RealityKitARContainer: View { @State private var text = "初始文本" var body: some View { VStack { HeaderView(text: $text) RealityKitARView(text: $text) } } }
解决办法
RealityKit中直接替换ModelEntity的mesh属性不会自动触发渲染更新,需要通过移除旧实体并添加新实体的方式实现同步,修复后的代码如下:
import SwiftUI import RealityKit struct RealityKitARView: UIViewRepresentable { @Binding var text: String func makeUIView(context: Context) -> ARView { let arView = ARView(frame: .zero) let anchor = AnchorEntity(plane: .horizontal) // 创建初始文本实体 let textEntity = createTextEntity(with: text) textEntity.position = SIMD3<Float>(0, 0.1, 0) anchor.addChild(textEntity) arView.scene.addAnchor(anchor) context.coordinator.textEntity = textEntity return arView } func updateUIView(_ uiView: ARView, context: Context) { guard let oldTextEntity = context.coordinator.textEntity else { return } // 移除旧文本实体 oldTextEntity.removeFromParent() // 创建新文本实体并添加到锚点 let newTextEntity = createTextEntity(with: text) newTextEntity.position = SIMD3<Float>(0, 0.1, 0) if let anchor = uiView.scene.anchors.first { anchor.addChild(newTextEntity) } context.coordinator.textEntity = newTextEntity } // 封装文本实体创建逻辑,统一配置 private func createTextEntity(with text: String) -> ModelEntity { let textMesh = MeshResource.generateText( text, extrusionDepth: 0.01, font: .systemFont(ofSize: 0.05) ) let textMaterial = SimpleMaterial(color: .red, isMetallic: false) return ModelEntity(mesh: textMesh, materials: [textMaterial]) } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject { var parent: RealityKitARView var textEntity: ModelEntity? init(_ parent: RealityKitARView) { self.parent = parent } } } // 其余视图代码保持不变 struct HeaderView: View { @Binding var text: String var body: some View { TextField("输入文本", text: $text) .padding() .background(Color.white) } } struct RealityKitARContainer: View { @State private var text = "初始文本" var body: some View { VStack { HeaderView(text: $text) RealityKitARView(text: $text) } } }
核心解决思路
- RealityKit的
ModelEntity修改mesh后不会自动触发场景重渲染,因此采用移除旧实体+添加新实体的方式完成更新 - 封装文本实体的创建逻辑,避免重复代码,保证每次生成的文本样式统一
- 在
updateUIView方法中定位到目标锚点,替换文本实体,实现AR文本与SwiftUI输入框的实时同步
内容的提问来源于stack exchange,提问作者justCubesAndText
相关产品推荐
相关产品推荐

