When switching from RealityView’s .spatialTracking camera mode to .virtual camera mode, the camera’s orientation relative to the scene is preserved permanently with no way to reset to default World-Up orientation. Since .spatialTracking’s camera mode will always have a non-default orientation, switching to .virtual camera mode ensures that the cameras’s ‘UP’ direction will never match the device display’s ‘UP’ direction as is default. This is especially noticeable when using .orbit camera controls, as the orbit’s UP direction matches the scene, not camera, and all rotation directions give unexpected results.
Expected: When setting virtual camera mode after using spatialTracking camera mode, either 1. The Virtual Camera orientation returns to default (world up). Or 2. A 'content.camera.resetOrientation()' call is made available which resets the RealityView camera to default orientation.
Reality: Switching from .spatialTracking -> .virtual camera mode permanently locks the .virtual camera’s orientation the final frame of the .spatialTracking camera’s rotation (relative to the RealityView content scene).
One imperfect workaround is to reset / rebuild the entire RealityView after changing modes (by resetting .id() or otherwise. This is not ideal as it causes everything inside the make closure to rerun, which not only is a performance & time cost, visually incurs a flicker and can also be problematic with managing increasingly complicated views. Another imperfect alternative is to use more than one RealityView - which is not ideal as it incurs double the base ram usage, significantly increases code, and seemingly goes against the intent of being able to change the camera .virtual/.spatatialTracking mode at will.
Code Sample:
import SwiftUI
import RealityKit
struct RKSpatialVirtualToggle: View {
@State var showAR: Bool = false
var body: some View {
RealityView { content in
let cube = ModelEntity(mesh: .generateBox(size: 0.25), materials: [SimpleMaterial()])
cube.position.z = -1
content.add(cube)
content.camera = showAR ? .spatialTracking : .virtual
content.cameraTarget = cube
} update: { content in
content.camera = showAR ? .spatialTracking : .virtual
}
.realityViewCameraControls(.orbit)
VStack{
Spacer()
Button("Toggle AR"){
showAR.toggle()
}
.buttonStyle(.borderedProminent)
}
}
}
Xcode Version: Version 26.0 (17A324) iOS Version: iOS 26.5 (23F75) Tested on devices, iPhone 12 Pro, iPhone 15 Pro