Article

Loading Entities from a File

Retrieve an entity from storage on disk using a synchronous or an asynchronous load operation.

Overview

Use a load method to bring an entity stored in a file into your app. You can load USD files (.usd, .usda, .usdc, .usdz) and Reality files (.reality) this way. You get a Reality file by exporting a project from the Reality Composer app, as described in Creating 3D Content with Reality Composer.

Load an Entity Hierarchy Synchronously

Use the load(named:in:) method to load an entity hierarchy from a USD or Reality file stored in a bundle. This method returns only after the operation completes. Omit the bundle parameter from the method call to load from the app’s main bundle:

let entity = try? Entity.load(named: "MyEntity") 

To load an entity stored at a specific location in the file system, create a file URL and use the load(contentsOf:withName:) method instead:

let url = URL(fileURLWithPath: "path/to/MyEntity.usdz")
let entity = try? Entity.load(contentsOf: url)

The load methods preserve the entity hierarchy in the loaded file and return the root entity in the scene that the USD or Reality file contains. The entity can have any number of descendant entities that you access using the methods of the HasHierarchy protocol. Accessing entities this way enables you to store and import sophisticated compositions from a single asset.

Load an Entity Hierarchy Asynchronously

Synchronous load operations block the thread on which you call them. To maintain a smooth user interface, it’s typically best to use an asynchronous load instead. All synchronous load operations have an asynchronous counterpart. For example, load from a bundle asynchronously by calling the loadAsync(named:in:) method:

_ = Entity.loadAsync(named: "MyEntity")   // From the app's main bundle.
    .sink(receiveCompletion: { loadCompletion in
        // Handle error.
    }, receiveValue: { entity in
        // Do something with `entity`.
    })

Asynchronous load operations return a LoadRequest instance that acts as a publisher. As shown in the snippet above, you can handle the published output in a closure by calling the load request’s sink(receiveCompletion:receiveValue:) method. But you can also access the full set of features provided by the Combine framework for publishers. For example, you can handle a group of loads in a single closure using the append(_:) and collect() methods:

_ = Entity.loadAsync(named: "MyEntity")
    .append(Entity.loadAsync(named: "MyOtherEntity"))
    .append(Entity.loadAsync(named: "MyThirdEntity"))
    .collect()
    .sink(receiveCompletion: { loadCompletion in
        // Handle error.
    }, receiveValue: { entities in
        // Handle the entire collection.
    })

Load an Anchor Entity

When you want to load a composition rooted by an anchor entity, you can instead use the loadAnchor(named:in:) method, or one of its siblings. These methods behave like the related load methods, except that they specifically return an AnchorEntity instance that you can add to your scene:

if let anchor = try? Entity.loadAnchor(named: "MyEntity") {
    arView.scene.addAnchor(anchor)
}

As with the load methods, the load anchor methods preserve the entity hierarchy.

Load a Flattened Model or Body-Tracked Entity

To load a model or body-tracked entity with internal structure that you don’t need to access, use the loadModel(named:in:) or the loadBodyTracked(named:in:) method, respectively. These methods and their siblings flatten the entity hierarchy into a single entity cast either as a ModelEntity or BodyTrackedEntity. A flattened entity can be easier to work with when you don’t need access to the entity’s details.

See Also

Essentials

class LoadRequest

A resource loader that acts as a publisher.