When you create an Augmented Reality Project using the standard Xcode template, Xcode adds this swift
file to your project:
//
// Experience.swift
// GENERATED CONTENT. DO NOT EDIT.
//
import Foundation
import RealityKit
import simd
import Combine
public enum Experience {
public enum LoadRealityFileError: Error {
case fileNotFound(String)
}
private static var streams = [Combine.AnyCancellable]()
public static func loadBox() throws -> Experience.Box {
guard let realityFileURL = Foundation.Bundle(for: Experience.Box.self).url(forResource: "Experience", withExtension: "reality") else {
throw Experience.LoadRealityFileError.fileNotFound("Experience.reality")
}
let realityFileSceneURL = realityFileURL.appendingPathComponent("Box", isDirectory: false)
let anchorEntity = try Experience.Box.loadAnchor(contentsOf: realityFileSceneURL)
return createBox(from: anchorEntity)
}
public static func loadBoxAsync(completion: @escaping (Swift.Result<Experience.Box, Swift.Error>) -> Void) {
guard let realityFileURL = Foundation.Bundle(for: Experience.Box.self).url(forResource: "Experience", withExtension: "reality") else {
completion(.failure(Experience.LoadRealityFileError.fileNotFound("Experience.reality")))
return
}
var cancellable: Combine.AnyCancellable?
let realityFileSceneURL = realityFileURL.appendingPathComponent("Box", isDirectory: false)
let loadRequest = Experience.Box.loadAnchorAsync(contentsOf: realityFileSceneURL)
cancellable = loadRequest.sink(receiveCompletion: { loadCompletion in
if case let .failure(error) = loadCompletion {
completion(.failure(error))
}
streams.removeAll { $0 === cancellable }
}, receiveValue: { entity in
completion(.success(Experience.createBox(from: entity)))
})
cancellable?.store(in: &streams)
}
private static func createBox(from anchorEntity: RealityKit.AnchorEntity) -> Experience.Box {
let box = Experience.Box()
box.anchoring = anchorEntity.anchoring
box.addChild(anchorEntity)
return box
}
public class Box: RealityKit.Entity, RealityKit.HasAnchoring {
public var steelBox: RealityKit.Entity? {
return self.findEntity(named: "Steel Box")
}
}
}
let's focus on the last part of the code
public class Box: RealityKit.Entity, RealityKit.HasAnchoring {
public var steelBox: RealityKit.Entity? {
return self.findEntity(named: "Steel Box")
}
}
this part is apparently loading the cube, named "Steel Box" from the standard Experience.rcproject
. But If I rename this string to any random name that is not on the scene, the cube still loads fine and so does the project... and this method is called during initialization!
Why is that? What is this really loading, or not?
A generated content in Experience.swift
file is directly linked to scenes coming from Reality Composer. steelBox
property is a "key" to model entity inside RC scene. It's made for developer's convenience to get a quick access to a desired model.
The string "Steel Box"
is not compulsory, it's rather optional. You can name your model whatever you want. However, you can even keep this string field empty (in that case Xcode assigns to it a long string of letters and digits or simply an empty string
instead of a modified name "Steel Box"
– and there will be no steelBox
property for you).
"Steel Box" name was automatically used to create `steelBox` property
So, for instance, if you named a model in Reality Composer scene "Plastic Sphere"
, it automatically creates a variable called plasticSphere
:
public var plasticSphere: Entity? { get }
In RealityKit you can access your cube entity this way:
let boxAnchor = try! Experience.loadBox()
arView.scene.anchors.append(boxAnchor)
print(boxAnchor.steelBox!)
or using a subscript for its hierarchy:
let boxAnchor = try! Experience.loadBox()
arView.scene.anchors.append(boxAnchor)
print(boxAnchor.children[0].children[0].children[0])
This results in printing Entity's hierarchy:
As we can see from Console "Steel Box"
is just a steelBox
's entity name.
print(boxAnchor.steelBox!.name as Any)
// "Steel Box"
However, as I said before, when you leave this field for model's name empty in Reality Composer...
...you can't retrieve your entity by its property name from scene.
You can retrieve it only using children's hierarchy:
let boxAnchor = try! Experience.loadBox()
arView.scene.anchors.append(boxAnchor)
print(boxAnchor.children[0].children[0].children[0])
So, as we can see there's no entity's name (string is empty) in Console now.
But you can assign it at any time:
boxAnchor.steelBox!.name = "My favorite box"