Search code examples
iosswiftswiftuiaugmented-realityrealitykit

How do I get MeshResource.generateText() to anchor to something other than the camera using RealityKit?


I'm using RealityKit and SwiftUI to place 3DText on iOS but I can't get the text to anchor to a position. I stripped the project down to the bare essentials below and it still doesn't work. The box will anchor and stay in one place as I walk around but the text will follow above my device wherever I move. This is driving me crazy because the box works totally as expected but the text just does not. I have tried so many different iterations of the code below to no avail. I was wondering if anyone else was having this problem or if it was just me, potentially a bug? Is there something else I should try?

import SwiftUI
import RealityKit

struct ContentView : View {
    var body: some View {
        return ARViewContainer().edgesIgnoringSafeArea(.all)
    }
}

struct ARViewContainer: UIViewRepresentable {
    
    func makeUIView(context: Context) -> ARView {
        
        let arView = ARView(frame: .zero)
    
        let anchor = AnchorEntity()
        anchor.position = simd_make_float3(0, -0.5, -1)
        let textEntity = ModelEntity(mesh: .generateText("Hello there", extrusionDepth: 0.4, font: .boldSystemFont(ofSize: 8), containerFrame: .zero, alignment: .center, lineBreakMode: .byWordWrapping))
        let boxEntity = ModelEntity(mesh: .generateBox(size: 0.2))
        anchor.addChild(textEntity)
        anchor.addChild(boxEntity)
        arView.scene.anchors.append(anchor)
        
        return arView
        
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {}
    
}

Here's everything the debug says if that's helpful:

2022-02-21 17:00:25.428134-0800 testARapp[4776:1686900] Metal GPU Frame Capture Enabled
2022-02-21 17:00:25.428586-0800 testARapp[4776:1686900] Metal API Validation Enabled
2022-02-21 17:00:25.797516-0800 testARapp[4776:1686900] [AssetTypes] Registering library (/System/Library/PrivateFrameworks/CoreRE.framework/default.metallib) that already exists in shader manager. Library will be overwritten.
2022-02-21 17:00:25.919915-0800 testARapp[4776:1686900] [Assets] Resolving material name 'engine:BuiltinRenderGraphResources/AR/suFeatheringCreateMergedOcclusionMask.rematerial' as an asset path -- this usage is deprecated; instead provide a valid bundle
2022-02-21 17:00:25.937834-0800 testARapp[4776:1686900] [Assets] Resolving material name 'engine:BuiltinRenderGraphResources/AR/arKitPassthrough.rematerial' as an asset path -- this usage is deprecated; instead provide a valid bundle
2022-02-21 17:00:25.938393-0800 testARapp[4776:1686900] [Assets] Resolving material name 'engine:BuiltinRenderGraphResources/AR/drPostAndComposition.rematerial' as an asset path -- this usage is deprecated; instead provide a valid bundle
2022-02-21 17:00:25.938882-0800 testARapp[4776:1686900] [Assets] Resolving material name 'engine:BuiltinRenderGraphResources/AR/arSegmentationComposite.rematerial' as an asset path -- this usage is deprecated; instead provide a valid bundle
2022-02-21 17:00:25.939438-0800 testARapp[4776:1686900] [Assets] Resolving material name 'engine:BuiltinRenderGraphResources/AR/arInPlacePostProcessCombinedPermute0.rematerial' as an asset path -- this usage is deprecated; instead provide a valid bundle
2022-02-21 17:00:25.940131-0800 testARapp[4776:1686900] [Assets] Resolving material name 'engine:BuiltinRenderGraphResources/AR/arInPlacePostProcessCombinedPermute1.rematerial' as an asset path -- this usage is deprecated; instead provide a valid bundle
2022-02-21 17:00:25.940383-0800 testARapp[4776:1686900] [Assets] Resolving material name 'engine:BuiltinRenderGraphResources/AR/arInPlacePostProcessCombinedPermute2.rematerial' as an asset path -- this usage is deprecated; instead provide a valid bundle
2022-02-21 17:00:25.947105-0800 testARapp[4776:1686900] [Assets] Resolving material name 'engine:BuiltinRenderGraphResources/AR/arInPlacePostProcessCombinedPermute3.rematerial' as an asset path -- this usage is deprecated; instead provide a valid bundle
2022-02-21 17:00:25.947365-0800 testARapp[4776:1686900] [Assets] Resolving material name 'engine:BuiltinRenderGraphResources/AR/arInPlacePostProcessCombinedPermute4.rematerial' as an asset path -- this usage is deprecated; instead provide a valid bundle
2022-02-21 17:00:25.947601-0800 testARapp[4776:1686900] [Assets] Resolving material name 'engine:BuiltinRenderGraphResources/AR/arInPlacePostProcessCombinedPermute5.rematerial' as an asset path -- this usage is deprecated; instead provide a valid bundle
2022-02-21 17:00:25.947841-0800 testARapp[4776:1686900] [Assets] Resolving material name 'engine:BuiltinRenderGraphResources/AR/arInPlacePostProcessCombinedPermute6.rematerial' as an asset path -- this usage is deprecated; instead provide a valid bundle
2022-02-21 17:00:25.948079-0800 testARapp[4776:1686900] [Assets] Resolving material name 'engine:BuiltinRenderGraphResources/AR/arInPlacePostProcessCombinedPermute7.rematerial' as an asset path -- this usage is deprecated; instead provide a valid bundle
2022-02-21 17:00:25.948513-0800 testARapp[4776:1686900] [Foundation.Serialization] Json Parse Error line 18: Json Deserialization; unknown member 'EnableARProbes' - skipping.
2022-02-21 17:00:25.948533-0800 testARapp[4776:1686900] [Foundation.Serialization] Json Parse Error line 20: Json Deserialization; unknown member 'EnableGuidedFilterOcclusion' - skipping.
2022-02-21 17:00:26.004695-0800 testARapp[4776:1686900] CoreText performance note: Client called CTFontCreateWithName() using name "System Font Semibold" and got font with PostScript name ".SFUI-Semibold". For best performance, only use PostScript names when calling this API.
2022-02-21 17:00:26.004723-0800 testARapp[4776:1686900] CoreText performance note: Set a breakpoint on CTFontLogSuboptimalRequest to debug.
2022-02-21 17:00:26.007971-0800 testARapp[4776:1686900] CoreText performance note: Client called CTFontCreateWithName() using name "System Font Regular" and got font with PostScript name ".SFUI-Regular". For best performance, only use PostScript names when calling this API.
2022-02-21 17:00:26.062646-0800 testARapp[4776:1686900] CoreText performance note: Client called CTFontCreateWithName() using name "System Font Semibold" and got font with PostScript name ".SFUI-Semibold". For best performance, only use PostScript names when calling this API.
2022-02-21 17:00:26.158252-0800 testARapp[4776:1686900] throwing -10878
2022-02-21 17:00:26.159086-0800 testARapp[4776:1686900] throwing -10878
2022-02-21 17:00:26.159123-0800 testARapp[4776:1686900] throwing -10878
2022-02-21 17:00:26.159156-0800 testARapp[4776:1686900] throwing -10878
2022-02-21 17:00:26.159189-0800 testARapp[4776:1686900] throwing -10878
2022-02-21 17:00:26.159344-0800 testARapp[4776:1686900] throwing -10878
2022-02-21 17:00:26.159449-0800 testARapp[4776:1686900] throwing -10878
2022-02-21 17:00:26.159576-0800 testARapp[4776:1686900] throwing -10878
2022-02-21 17:00:26.159643-0800 testARapp[4776:1686900] throwing -10878
2022-02-21 17:00:28.011153-0800 testARapp[4776:1687256] [Technique] ARWorldTrackingTechnique <0x131f0d840>: World tracking performance is being affected by resource constraints [25]

Solution

  • After it's anchored, try printing out the bounding sphere of the text entity relative to the world space, to see if that's changing at all. Maybe print it a few times while moving around using a screen tap gesture etc.

    I suspect the text object you're making is bigger than it looks and further away, making it look as though it's sticking to the screen due to perspective. I've had a lot of problems with generating text and RealityKit. There's a small class in a package I made that helps a lot with all these text related weirdness to do with its centre, size etc: RealityUI, RUIText.

    As well as that, anchoring to the floor with an offset position 0.5m above a 1x1m horizontal plane like this would make for a better anchor point:

    let anchor = AnchorEntity(.plane(
        [.horizontal], classification: .any, minimumBounds: [1, 1])
    )
    anchor.position.y = 0.5