Theuns Botha
Theuns Botha

Reputation: 31

How to add a new scene to an existing anchor and remove the previous scene?

I have an rcproject file with about 12 scenes (500mb or so). In order to lessen the load on iOS devices I tried breaking it apart into separate rcproject files and change the scene using notification triggers. However when doing this and adding the new scene as a child to the main anchor, the new scene renders in a new spot, breaking the AR experience. There must be a way to add the new scenes to the exact same anchor/position. Alternatively, is there a better way than seperating the rcproject to lessen load on ram etc?

Here is my ARView

struct ARViewContainer: UIViewRepresentable {

func makeUIView(context: Context) -> ARView {
    
    let arView = ARView(frame: .zero)
    // The experience consists of a "Base" (it acts as a permanent platform for all the scenes to be rendered on)        
    let baseAnchor = try! Base.loadIntro()
    let introAnchor = try! IntroSceneOM.loadIntro()

    
    introAnchor.actions.changeStoriesWithTrigger.onAction = loadStories
    
    arView.scene.anchors.append(baseAnchor)
    
    arView.scene.anchors.append(introAnchor)
    
    func loadStories(_ entity: Entity?) -> Void {
        arView.scene.anchors.remove(introAnchor)

        let storiesAnchor = try! StoriesSceneOM.loadStoriesScene()
        
        baseAnchor.addChild(storiesAnchor)
    }
    
    return arView
    
}

func updateUIView(_ uiView: ARView, context: Context) {} }

EDIT:

Recreated the project using an implementation of Andy Jazz's code.

    func makeUIView(context: Context) -> ARView {
    
    let arView = ARView(frame: .zero)
    
    var anchor = AnchorEntity()

    let scene01 = try! Experience.loadBoxScene()
    let scene02 = try! Experience.loadBallScene()
    
    // Base Scene
    
    let scene03 = try! Experience.loadFloppyScene()
    
    anchor = AnchorEntity(.plane(.horizontal, classification: .any,
                                                     minimumBounds: [0.1, 0.1]))
    
    scene01.actions.boxTapped.onAction = loadScene02
    scene02.actions.ballTapped.onAction = loadScene01
    
    anchor.addChild(scene01)
    anchor.addChild(scene03)
    arView.scene.anchors.append(anchor)
    
    func loadScene02(_ entity: Entity?) -> Void {
        scene01.removeFromParent()
        anchor.addChild(scene02)
    }
    
    func loadScene01(_ entity: Entity?) -> Void {
        scene02.removeFromParent()
        anchor.addChild(scene01)
    }
    
    return arView
}

However I still get the same issue where the anchor moves each time a new scene is added.

First Scene Second Scene

Upvotes: 2

Views: 924

Answers (1)

Andy Jazz
Andy Jazz

Reputation: 58093

The code is quite simple, but regarding the issue of loading scenes with a large number of polygons, remains unresolved. At the maximum, the current scene should contain no more than 100K polygons, but ideally they should be within 50...70K. Texture resolution should not exceed 2K.

import RealityKit

class ViewController: UIViewController {
    
    @IBOutlet var arView: ARView!
    @IBOutlet var label: UILabel!
    var anchor = AnchorEntity()
    let scene01 = try! Experience.loadBox()
    let scene02 = try! Experience.loadBall()
    var cube = ModelEntity()
    var sphere = ModelEntity()
    
    override func viewDidLoad() {
        super.viewDidLoad()            
        self.cube = scene01.steelBox?.children[0] as! ModelEntity
        self.sphere = scene02.ball?.children[0] as! ModelEntity
        
        self.anchor = AnchorEntity(.plane(.horizontal, classification: .any,
                                                 minimumBounds: [0.1, 0.1]))
        self.anchor.addChild(cube)
        arView.scene.anchors.append(anchor)
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
            self.label.text = String(describing: self.anchor.id)
        }
    }        
    @IBAction func pressed(_ sender: UIButton) {
        self.cube.removeFromParent()
        self.anchor.addChild(sphere)
        self.label.text = String(describing: self.anchor.id)
    }
}

Upvotes: 1

Related Questions