如何维持ARWorldTrackingConfiguration运行并保留AR场景状态?
Hey Hugo.W, let's break down how to solve your two ARKit challenges—these are super common pain points when navigating between view controllers in AR apps!
1. Keeping ARWorldTrackingConfiguration Running Continuously
By default, ARKit pauses the session when your ARViewController's view disappears (like when you push another VC). Here's how to override that:
Skip the default session pause in view lifecycle methods
OverrideviewWillDisappearto avoid letting ARKit pause the session automatically. Just make sure you handle any necessary cleanup without stopping tracking:override func viewWillDisappear(_ animated: Bool) { // Don't call super.viewWillDisappear(animated) to bypass default pause behavior // Add any custom cleanup logic here (e.g., hiding UI elements) arView.session.paused = false // Explicitly keep the session running }Use a shared ARSession singleton (more robust)
For cases where you might destroy and recreate the ARViewController, move the ARSession to a singleton class. This decouples the session from the VC's lifecycle:class ARSessionManager { static let shared = ARSessionManager() let session = ARSession() private init() {} // Enforce singleton pattern }Then in your ARViewController, hook into the shared session on load:
override func viewDidLoad() { super.viewDidLoad() arView.session = ARSessionManager.shared.session // Only configure and run the session if it's not already active if arView.session.configuration == nil { let config = ARWorldTrackingConfiguration() arView.session.run(config) } }⚠️ Heads up: Running ARSession in the background uses more battery and requires proper camera permissions. Only do this if your app truly needs continuous tracking.
2. Preserving Scene Nodes and World Origin When Returning
The key here is avoiding unnecessary session resets and keeping your scene state intact:
Keep the ARViewController in memory
If you're using aUINavigationController, pushing a new VC and popping back won't deallocate the ARViewController. All your existing nodes will stay attached toarView.scene.rootNode, so you won't lose anything when you return.Save and restore the ARWorldMap (if you must recreate the VC)
If you have to destroy and reinitialize the ARViewController (e.g., modal presentation with a new instance), useARWorldMapto save the tracking origin:- Capture the world map before leaving the ARViewController:
func saveCurrentWorldMap() -> ARWorldMap? { guard let worldMap = arView.session.currentFrame?.worldMap else { print("Failed to capture world map") return nil } return worldMap } - Store this map in an accessible place (like the singleton we created earlier, or pass it to the next VC).
- Load the map when initializing the new ARViewController to restore tracking:
if let savedMap = ARSessionManager.shared.savedWorldMap { let config = ARWorldTrackingConfiguration() config.initialWorldMap = savedMap // Use these options to match the saved state arView.session.run(config, options: [.resetTracking, .removeExistingAnchors]) // Re-add your 3D nodes to the scene here using their original positions }
- Capture the world map before leaving the ARViewController:
Avoid unnecessary session resets
Never callarView.session.run(config, options: [.resetTracking])every time the view appears. Only run the session once onviewDidLoad, unless you explicitly need to reset tracking for a new session.
内容的提问来源于stack exchange,提问作者Hugo.W

