Search code examples
swiftxcodeviewcontrollerarkitrealitykit

Adding a Welcome ViewController screen in front of ViewController ARSession


I'm developing an app and I wanted to add a "Welcome!" screen with a button that would take the user to the AR session. The AR session is setup on the first View Controller, as it normally is. What would be the best way to add a screen (not the splash screen) that prompts the user to enter the AR session? I tried creating a new ViewController and including the code before the existing code, but that wasn't working for me. I've never really done a change of screens like this, so any advice is greatly appreciated!

import UIKit
import RealityKit
import ARKit
    

 class ViewController: UIViewController, ARSessionDelegate {
     //delay app launch to show splash screen
    func application(_ application: UIApplication, didFinishLaunchingWithOptions 
  launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        Thread.sleep(forTimeInterval: 3.0)
        // Override point for customization after application launch.
        return true
    }
  //end splash screen delay
  @IBOutlet var arView: ARView!

  override func viewDidLoad() {
    super.viewDidLoad()
 
    arView.session.delegate = self
    
    showModel()
    overlayCoachingView()
    setupARView()
    
    arView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap(recognizer:))))
    
}

func showModel(){
    
    let anchorEntity = AnchorEntity(plane: .horizontal, minimumBounds:[0.7, 0.7])
    
   anchorEntity.scale = [0.2, 0.2, 0.2]
    
    let entity = try! Entity.loadModel(named: "COW_ANIMATIONS")
    entity.setParent(anchorEntity)
    
    arView.scene.addAnchor(anchorEntity)
    

}
//Overlay coaching view "adjust iphone scan"
func overlayCoachingView () {
    
    let coachingView = ARCoachingOverlayView(frame: CGRect(x: 0, y: 0, width: 
 arView.frame.width, height: arView.frame.height))
    
    coachingView.session = arView.session
    coachingView.activatesAutomatically = true
    coachingView.goal = .horizontalPlane
    
    view.addSubview(coachingView)
    
}//end overlay
    

func setupARView(){
    arView.automaticallyConfigureSession = false
    let configuration = ARWorldTrackingConfiguration()
    configuration.planeDetection = [.horizontal, .vertical]
    configuration.environmentTexturing = .automatic
    arView.session.run(configuration)
}

//object placement

@objc
func handleTap(recognizer: UITapGestureRecognizer){
    let location = recognizer.location(in:arView)
    
    let results = arView.raycast(from: location, allowing: .estimatedPlane, alignment: .horizontal)
    
    if let firstResult = results.first {
        let brownCowAnchor = ARAnchor(name: "COW_ANIMATIONS", transform: firstResult.worldTransform)
        arView.session.add(anchor: brownCowAnchor)
    } else {
        print("Object placement failed - couldn't find surface.")
        
        
        
        //cow animations
        //let robot = try! ModelEntity.load(named: "COW_ANIMATIONS")
       let brownCowAnchor = AnchorEntity()
        let blackCowAnchor = AnchorEntity()
  
        //anchor.children.append(robot)
        //arView.scene.anchors.append(anchor)

        //robot.playAnimation(robot.availableAnimations[0].repeat(duration: .infinity),
                                                      //transitionDuration: 0.5,
                                                            //startsPaused: false)
        
        //start cow animation
        
        
        let brownCow = try! ModelEntity.load(named: "COW_ANIMATIONS")
        let blackCow = try! ModelEntity.load(named: "Cow")

        brownCow.position.x = -1.0
        blackCow.position.x = 1.0
        brownCowAnchor.position.z = -2.0
        blackCowAnchor.position.z = -2.0
        brownCow.setParent(brownCowAnchor)
        blackCow.setParent(blackCowAnchor)
        arView.scene.anchors.append(brownCowAnchor)
        arView.scene.anchors.append(blackCowAnchor)
        
        let cowAnimationResource = brownCow.availableAnimations[0]
        let horseAnimationResource = blackCow.availableAnimations[0]

        brownCow.playAnimation(cowAnimationResource.repeat(duration: .infinity),
                                            transitionDuration: 1.25,
                                                  startsPaused: false)

        blackCow.playAnimation(horseAnimationResource.repeat(duration: .infinity),
                                                transitionDuration: 0.75,
                                                      startsPaused: false)
        
        //end cow animations
    }
  }
  
  func placeObject(named entityName: String, for anchor: ARAnchor)  {
    let entity = try! ModelEntity.loadModel(named: entityName)
    
    entity.generateCollisionShapes(recursive: true)
    arView.installGestures([.rotation, .translation], for: entity)
    
    
    let anchorEntity = AnchorEntity(anchor: anchor)
    anchorEntity.addChild(entity)
    arView.scene.addAnchor(anchorEntity)
    
    
   }
 }

Solution

  • First, you can drag the arrow in the storyboard to set your initial view controller. drag the arrow

    Then, make a new UIViewController class for the welcome screen.

    class WelcomeViewController: UIViewController {
    
    
    }
    

    Then, inside the storyboard, set the welcome view controller to WelcomeViewController class.

    set the class

    Connect the "Let's go" button to WelcomeViewController via an @IBAction. add ibaction

    Inside the @IBAction, do this:

    @IBAction func goPressed(_ sender: Any) {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        if let viewController = storyboard.instantiateViewController(withIdentifier: "ViewController") as? ViewController {
            self.present(viewController, animated: true, completion: nil) /// present the view controller (the one with the ARKit)!
        }
    }
    

    Then, go back to the storyboard, and set the Storyboard ID to the main view controller (the one with the ARSCNView) to ViewController:

    set storyboard ID

    That's it!