如何在Swift Package Manager中添加Reality文件?

问题描述

我听说过Xcode 12(现在是Beta 6),Swift软件包管理器现在可以包含资源。但是我无法打开现实(.rcproject)文件

这是我尝试过的; (并且您可以复制)

  1. 我创建了一个新的Augmented Reality App项目。 (RealityKit + SwiftUI + Swift)
  2. 现在,如果您尝试运行该项目,那么一切正常,您将看到一个认的金属框。
  3. 现在我创建了一个新的SPM(Swift软件包管理器)
  4. 现在,我将本地创建的SPM拖到项目中,并将其添加到“常规”>“目标”选项卡中的框架中。 (向项目通知本地添加的spm)
  5. 我将Experience.rcprojectContentView(还复制了自动生成Experience枚举,您可以通过Cmd + Click将该枚举复制到)SPM
  6. 修复了ContentView的一些访问初始化问题,并在platforms: [.iOS(.v13)],添加了平台支持SPM
  7. resources中为路径SPM添加Experience.rcproject

完成这些步骤后,除了要让AR包含快速程序包管理器外,我是。
但是自动生成Experience枚举会引发.fileNotFound("Experience.reality")错误
似乎仍然无法在Bundle中找到现实文件

您是否尝试过类似的方法。等待任何帮助。谢谢。


Folder Structure

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",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")
        }

    }

}

ContentView文件中,我简单地显示EKARView

解决方法

Xcode知道如何在构建应用程序时将.rcproject文件处理成所需的.reality文件。不幸的是,使用Swift包访问项目文件时,无法完成此处理。

您概述的步骤几乎可以正常工作。最终的结果是使用已经编译的.reality文件代替.rcproject文件。为了转换默认的.rcproject文件,您需要使用Apple的 Reality Composer 应用程序。

使用Xcode 12概述的步骤...

  • 选择Experience.rcproject文件后,单击“在Reality Composer中打开”按钮。
  • 打开后,通过“文件”菜单导出项目。
  • 选择“项目”,然后单击“导出”。这将产生一个Experience.reality文件。
  • 将该文件放入您的快速包资源中。
  • 请确保将Bundle文件中的Experience.swift引用替换为Bundle.module,因为现有引用将以您的应用程序包为目标。