【问题标题】:Dynamically change text of RealityKit entity动态更改 RealityKit 实体的文本
【发布时间】:2019-10-11 22:13:39
【问题描述】:

我使用 Reality Composer 创建了一个非常简单的场景(“SpeechScene”),其中单个语音标注对象(“Speech Bubble”)锚定到 Face 锚点。

我已通过以下方式将此场景加载到代码中:

let speechAnchor = try! Experience.loadSpeechScene()
arView.scene.anchors.append(speechAnchor)

let bubble = (arView.scene as? Experience.SpeechScene)?.speechBubble

它按预期呈现。但是,我想动态地更改这个现有实体的文本。

我发现了一个类似的问题here,但我不清楚如何引用普通RealityKit.Entity 对象的meshResource 属性。

这可能吗?谢谢!

【问题讨论】:

  • 我更新了答案。

标签: swift augmented-reality arkit realitykit reality-composer


【解决方案1】:

第一种方法

首先,您需要找出 Reality Composer 场景中包含Bubble Speech 对象的层次结构。为此,我使用了简单的 print() 命令:

print(textAnchor.swift!.children[0].components.self)   /* Bubble Plate */

print(textAnchor.swift!.children[1].components.self)   /* Text Object */

现在我可以提取一个文本实体对象了:

let textEntity: Entity = textAnchor.swift!.children[1].children[0].children[0]

和气泡板实体对象:

let bubbleEntity: Entity = textAnchor.swift!.children[0]

这是您可以根据需要调整的最终代码版本:

import RealityKit

class GameViewController: UIViewController {
    
    @IBOutlet var arView: ARView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let textAnchor = try! SomeText.loadTextScene()
        
        let textEntity: Entity = textAnchor.swift!.children[1].children[0].children[0]

        textAnchor.swift!.parent!.scale = [4,4,4]  // Scale for both objects
        
        var textModelComp: ModelComponent = (textEntity.components[ModelComponent])!
                
        var material = SimpleMaterial()
        material.baseColor = .color(.red)
        textModelComp.materials[0] = material

        textModelComp.mesh = .generateText("Obj-C",
                            extrusionDepth: 0.01,
                                      font: .systemFont(ofSize: 0.08),
                            containerFrame: CGRect(),
                                 alignment: .left,
                             lineBreakMode: .byCharWrapping)

        textEntity.position = [-0.1,-0.05, 0.01]

        textAnchor.swift!.children[1].children[0].children[0].components.set(textModelComp)
        arView.scene.anchors.append(textAnchor)
    }
}


第二种方法

对于这种情况,您始终可以使用更简单的方法 - 在 Reality Composer 中创建多个场景,每个场景必须包含不同的 speech-object

请注意,此代码不是用于跟踪,它只是使用Tap Gesture 动态切换两个对象的测试。然后你需要修改这段代码来跟踪人脸。

import RealityKit

class ViewController: UIViewController {
    
    @IBOutlet var arView: ARView!
    var counter = 0
    var bonjourObject: FaceExperience.Bonjour? = nil
    var holaObject: FaceExperience.Hola? = nil
     
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Reality Composer Scene named "Bonjour"
        // Model name – "french"
        bonjourObject = try! FaceExperience.loadBonjour()
        bonjourObject?.french?.scale = SIMD3(x: 2, y: 2, z: 2)
        bonjourObject?.french?.position.y = 0.25
        
        // Reality Composer Scene named "Hola"
        // Model name – "spanish"
        holaObject = try! FaceExperience.loadHola()
        holaObject?.spanish?.scale = SIMD3(x: 2, y: 2, z: 2)
        holaObject?.spanish?.position.z = 0.3
    }
    @IBAction func tapped(_ sender: UITapGestureRecognizer) {            
        if (counter % 2) == 0 {
            arView.scene.anchors.removeAll()
            arView.scene.anchors.append(holaObject!)
        } else {
            arView.scene.anchors.removeAll()
            arView.scene.anchors.append(bonjourObject!)
        }
        counter += 1
    }
}

如果您希望文本部分位于同一位置 - 只需将对象从一个场景复制粘贴到另一个场景即可。

【讨论】:

    【解决方案2】:

    @maxxfrazer 的断言是正确的,即当前动态更改文本的唯一方法是替换 EntityModelComponent,当然前提是它遵守 HasModel Protocol

    我写了一个简单的扩展来帮助解决这个问题:

    //-------------------------
    //MARK: - Entity Extensions
    //-------------------------
    
    extension Entity{
    
      /// Changes The Text Of An Entity
      /// - Parameters:
      ///   - content: String
      func setText(_ content: String){ self.components[ModelComponent] = self.generatedModelComponent(text: content) }
    
      /// Generates A Model Component With The Specified Text
      /// - Parameter text: String
      func generatedModelComponent(text: String) -> ModelComponent{
    
        let modelComponent: ModelComponent = ModelComponent(
    
          mesh: .generateText(text, extrusionDepth: TextElements().extrusionDepth, font: TextElements().font,
                              containerFrame: .zero, alignment: .center, lineBreakMode: .byTruncatingTail),
    
          materials: [SimpleMaterial(color: TextElements().colour, isMetallic: true)]
    
        )
    
        return modelComponent
      }
    
    }
    
    //--------------------
    //MARK:- Text Elements
    //--------------------
    
    /// The Base Setup Of The MeshResource
    struct TextElements{
    
      let initialText = "Cube"
      let extrusionDepth: Float = 0.01
      let font: MeshResource.Font = MeshResource.Font.systemFont(ofSize: 0.05, weight: .bold)
      let colour: UIColor = .white
    
    }
    

    为了使用它,假设您创建了一个名为 textEntityEntity

     var textEntity = Entity()
    

    然后,您可以随时通过替换ModelComponent 和设置MeshResource 来设置动态更改文本,只需调用以下方法:

    textEntity.setText("Stack Overflow")
    

    当然,关于居中或对齐文本,您需要做一些简单的计算(我在这里省略了)。

    希望对你有帮助。

    【讨论】:

      【解决方案3】:

      找到您的模型实体(可能通过放置断点并最初查看子实体),找到符合 HasModel 协议的实体,然后使用 generatetext 将其模型替换为不同的模型:

      https://developer.apple.com/documentation/realitykit/meshresource/3244422-generatetext

      【讨论】:

        猜你喜欢
        • 2011-07-28
        • 2021-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多