如何在 Swift 包管理器中添加 Reality 文件?

How to add Reality file in a Swift Package Manager?

我听说 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+单击找到它)到 SPM
  6. 修复了 ContentView 的一些访问初始化程序问题并在 SPM
  7. 中添加了平台支持 platforms: [.iOS(.v13)],
  8. SPM 中为路径 Experience.rcproject 添加 resources exist

完成这些步骤后,除了包含一个 AR swift 包管理器外,我还想。
但是自动生成的 Experience 枚举会抛出 .fileNotFound("Experience.reality") 错误。
似乎仍然无法在 Bundle 中找到现实文件?

你试过类似的东西吗?等待任何帮助。谢谢..


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 { [=13=] === 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 文件后,单击 'Open in Reality Composer' 按钮。
  • 打开后,通过 'File' 菜单导出项目。
  • 选择'Project'并点击导出。这会生成一个 Experience.reality 文件。
  • 将该文件放入您的 swift 包资源中。
  • 确保将 Experience.swift 文件中的 Bundle 引用替换为 Bundle.module,因为现有引用将针对您的应用程序包。