RealityKit – Asynchronous model loading doesn't work
Use the following macOS code version to find out how to load model asynchronously:
import AppKit
import RealityKit
import Combine
class GameViewController: NSViewController {
@IBOutlet var arView: ARView!
var model: ModelEntity? = nil
let anchor = AnchorEntity()
var cancellable: AnyCancellable? = nil
override func awakeFromNib() {
arView.environment.background = .color(.systemTeal)
cancellable = Entity.loadModelAsync(named: "Glasses.usdz")
.sink(receiveCompletion: { completion in
if case let .failure(error) = completion {
print("Unable to load a model due to error \(error)")
}
self.cancellable?.cancel()
}, receiveValue: { [self] (model: Entity) in
if let model = model as? ModelEntity {
self.model = model
cancellable?.cancel()
print("Congrats! Model is successfully loaded!")
anchor.addChild(model)
anchor.position = [0.4, 1.5, -1]
anchor.scale = [300, 300, 300] // set appropriate scale
arView.scene.anchors.append(anchor)
}
})
}
}
Loading anchor from url async doesnt work
You have to store subscriber somewhere in member
// somewhere above
private var subscribers: Set<AnyCancellable>()
...
if let url = url {
let loadRequest = Entity.loadAnchorAsync(contentsOf: url)
loadRequest.sink(receiveCompletion: { completion in
// handle completion
}, receiveValue: { anchor in
self.arView.scene.addAnchor(anchor)
}).store(in: &self.subscribers) // << keep it alive
} else {
fatalError("no url")
}
Error in displaying reality file from network
Uploading a .reality
model from web works fine. You can easily check this in Xcode Simulator:
import UIKit
import RealityKit
class ViewController: UIViewController {
@IBOutlet var arView: ARView!
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://developer.apple.com/augmented-reality/quick-look/models/cosmonaut/CosmonautSuit_en.reality")
let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let destination = documents.appendingPathComponent(url!.lastPathComponent)
let session = URLSession(configuration: .default,
delegate: nil,
delegateQueue: nil)
var request = URLRequest(url: url!)
request.httpMethod = "GET"
let downloadTask = session.downloadTask(with: request, completionHandler: { (location: URL?,
response: URLResponse?,
error: Error?) -> Void in
let fileManager = FileManager.default
if fileManager.fileExists(atPath: destination.path) {
try! fileManager.removeItem(atPath: destination.path)
}
try! fileManager.moveItem(atPath: location!.path,
toPath: destination.path)
DispatchQueue.main.async {
do {
let model = try Entity.loadAnchor(contentsOf: destination)
self.arView.scene.addAnchor(model)
} catch {
print("Fail loading entity.")
}
}
})
downloadTask.resume()
}
}
RealityKit – How to add motion to a loaded ModelEntity from USDZ file?
Add to your code .generateCollisionShapes(recursive:)
instance method for every participant (entity) that not only creates collision's shapes but also allows you to simulate physics.
import SwiftUI
import RealityKit
struct ARViewContainer: UIViewRepresentable {
let boxx = ModelEntity(mesh: .generateBox(size: 0.5))
let ball = ModelEntity(mesh: .generateSphere(radius: 0.25))
let anchor = AnchorEntity()
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
// BALL
ball.physicsBody = .init()
ball.physicsMotion = .init()
ball.physicsMotion?.linearVelocity = [10,0,0]
ball.position.x = -3
ball.generateCollisionShapes(recursive: true)
anchor.addChild(ball)
// BOX
boxx.physicsBody = .init()
boxx.physicsMotion = .init()
boxx.physicsMotion?.linearVelocity = [0,2,0]
boxx.generateCollisionShapes(recursive: true)
anchor.addChild(boxx)
// Anchor
anchor.position.z = -3
arView.scene.addAnchor(anchor)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) { }
}
...
struct ContentView : View {
var body: some View {
return ARViewContainer().edgesIgnoringSafeArea(.all)
}
}
For more details, read THIS post.
Available animations collection is empty, while using .loadModelAsync()
Use ModelEntity.loadAsync
. It loads full hierarchy including animation.
import RealityKit
import Combine
let anchor = AnchorEntity()
var cancellable: AnyCancellable? = nil
self.cancellable = ModelEntity.loadAsync(named: "biplane.usdz").sink(
receiveCompletion: { completion in
if case let .failure(error) = completion {
print("Unable to load a model \(error)")
}
self.cancellable?.cancel()
},
receiveValue: { [self] planeModel in
let animation = planeModel.availableAnimations[0]
anchor.addChild(planeModel)
anchor.position = [0, 0,-2]
anchor.scale = [0.1, 0.1, 0.1]
arView.scene.anchors.append(anchor)
planeModel.playAnimation(animation.repeat(count: .max))
}
)
Related Topics
Why Is Swift Giving Me Inaccurate Floating Point Arithmetic Results
Swift Applications Takes More Space on Disk
Have Label Appear with Delay in Swift
Images Being Flipped When Adding to Nsattributedstring
Sharing Button Works Perfectly on iPhone But Crash on Ipad
Leaks in Navigationview/List/Foreach with Dynamically Generated Views
Parse Nested Completion Handlers
Synchronous Request Using Alamofire
How to Get My Button to Reflect The Bool of My Environmentobject
Audiounit Callback and Synchronization: How to Ensure Thread Safety with Gcd
Swift 1.2 Assigning Let After Initialization
Drawing at Cocoa with Swift Creates an Error
Why Is My App Returning Hundreds of Errors That Say "Undefinedsymbol"
How to Resize an Image That Is Being Printed
Avspeechsynthesizer Isspeaking Not Working in Swift
Swift Video to Document Directory