简体   繁体   中英

How to add Reality file in a Swift Package Manager?

I've heard with the Xcode 12 (now in Beta 6), Swift package manager is now able to include resources. But I am not able to open a reality (.rcproject) file.

Here is what I have tried; (& you can reproduce)

  1. I created a new Augmented Reality App project. (RealityKit + SwiftUI + Swift)
  2. Now if you try to run the project, everything works, you see a default metallic box.
  3. Now I created a new SPM (Swift package manager)
  4. Now I dragged locally created SPM to the project and added it to frameworks in General > Targets tab. (To inform the project about locally added spm)
  5. I dragged Experience.rcproject & ContentView (also copied the autogenerated Experience enum, you can reach it via Cmd+Click) to SPM
  6. Fixed some access initializer issue for ContentView & added platform support platforms: [.iOS(.v13)], in the SPM
  7. Added resources in the SPM for the path Experience.rcproject exist

After those steps finished I'd except to have an AR included swift package manager.
But auto generated Experience enum throws .fileNotFound("Experience.reality") error.
Seems still not able to find reality file in Bundle?

Have you tried something similar. Waiting any helps. Thanks..


文件夹结构

Package.swift

// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "ARSPM",
    platforms: [.iOS(.v13)],
    products: [
        .library(
            name: "ARSPM",
            targets: ["ARSPM"]),
    ],
    dependencies: [],
    targets: [
        .target(
            name: "ARSPM",
            dependencies: [], resources: [
                .copy("Resources")
            ]),
        .testTarget(
            name: "ARSPMTests",
            dependencies: ["ARSPM"]),
    ]
)

ARView.swift

import SwiftUI
import RealityKit

public struct EKARView : View {
    public init() { }
    public var body: some View {
        return ARViewContainer().edgesIgnoringSafeArea(.all)
    }
}

public struct ARViewContainer: UIViewRepresentable {
    
    public func makeUIView(context: Context) -> ARView {
        
        let arView = ARView(frame: .zero)
        
        // Load the "Box" scene from the "Experience" Reality File
        let boxAnchor = try! Experience.loadBox()
        
        // Add the box anchor to the scene
        arView.scene.anchors.append(boxAnchor)
        
        return arView
        
    }
    
    public func updateUIView(_ uiView: ARView, context: Context) {}
    
}

GeneratedExperienceFile.swift

//
// Experience.swift
// GENERATED CONTENT. DO NOT EDIT.
//

import Foundation
import RealityKit
import simd
import Combine

internal 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 =
//                Also tried >> Foundation.Bundle.module
                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")
        }

    }

}

And in ContentView file, I simple show EKARView .

Xcode knows how to process a .rcproject file into the .reality file it needs when building an application. Unfortunately this processing isn't done when accessing the project file using a Swift Package.

The steps you've outlined will almost work. What it comes down to is using the already compiled .reality file in place of the .rcproject file. In order to transform the default .rcproject file, you'll need to use Apple's Reality Composer application.

steps outlined using Xcode 12...

  • With the Experience.rcproject file selected, click the 'Open in Reality Composer' button.
  • Once open, export the project through the 'File' menu.
  • Choose 'Project' and click export. This produces a Experience.reality file.
  • Place that file in your swift package resources.
  • Make sure replace the Bundle references in your Experience.swift file with Bundle.module , as the existing reference will target your application bundle.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM