user7289922
user7289922

Reputation: 421

Add new entity to visionOS realityView after API call completes

I am trying to add a new entity to visionOS RealityView after API call completes. I am simulating API call with a timer, and I want to add add a sphere at a new position every second. The timer adjusts location.x and the update block should add sphere at a new position. I think update block is not the right place to do this. How do I achieve this? Thanks!


import SwiftUI
import RealityKit
import RealityKitContent

struct ContentView: View {

    @State var location: SIMD3<Float> = SIMD3<Float>(x: 0, y: 0, z: 0)

    var body: some View {
        VStack {
            RealityView { content in
                let data = getSphere(location: SIMD3<Float>(x: 0.2, y: 0.2, z: 0.2), color: .blue)
                content.add(data)
                
            } update: { content in
               
                // 1 - By doing ``` location.x += 1``` the update block is trigerred
                print("update triggered") // => this logs as expected
                
                // 2 - I want to add a NEW sphere at adjusted location, it is not working though
                let data = getSphere(location: SIMD3<Float>(x: location.x, y: 0.7, z: 0.2), color: .orange)
                content.add(data) // not working
                content.entities.append(data) // also not working
            }
            .onAppear {
                // 3 - Simulate API call with timer
                Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { t in
                    location.x += 1.0
                }
            }
        }
    }
}

func getSphere(location: SIMD3<Float>, color: SimpleMaterial.Color) -> ModelEntity {
    let sphere = ModelEntity(mesh: .generateSphere(radius: 0.03))
    let material = SimpleMaterial(color: color, isMetallic: false)
    sphere.model?.materials = [material]
    sphere.position = location
    return sphere
}

Upvotes: 1

Views: 1049

Answers (1)

Andy Jazz
Andy Jazz

Reputation: 58143

Your code works fine. You just need to set a smaller step for the orange sphere and increase the size of the Volumetric container to the maximum (in case you're using a volume). To go beyond the limits of a volumetric window use Fully Immersive VR experience or Mixed Immersion AR style.

import SwiftUI
import RealityKit

@main struct YourApp : App {
    var body: some Scene {
        ImmersiveSpace(id: "mine") {
            ContentView()
        }
        .immersionStyle(selection: .constant(.mixed), in: .mixed)
    }
}

func getSphere(_ pos: SIMD3<Float>, _ col: SimpleMaterial.Color) -> ModelEntity {
    let sphere = ModelEntity(mesh: .generateSphere(radius: 0.03),
                        materials: [SimpleMaterial(color: col, isMetallic: false)])
    sphere.position = pos
    return sphere
}

struct ContentView : View {
    @State var location = SIMD3<Float>()

    var body: some View {
        RealityView { content in
            let data = getSphere([0.0, 0.3, 0.2], .blue)
            content.add(data)
        } update: { content in
            let data = getSphere([location.x, 0.2, 0.2], .orange)
            content.add(data)
        }
        .onAppear {
            Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in
                location.x += 0.1
            }
        }
    }
}

enter image description here

Upvotes: 2

Related Questions