You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过键盘修改并实时更新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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 04:17:08