了解RealityKit中各个部分的联系。

概述

RealityKit是一个用于构建应用程序、游戏和其他沉浸式体会的3D结构。尽管它是用面向目标的语言构建的,并运用面向目标的规划原则,但RealityKit的架构避免了很多运用组合的办法——其中目标是经过增加持有对其他目标的引用的实例变量来构建的——而是采用了一种依据实体组件体系(Entity Component System,ECS)的模块化规划,将应用程序目标分为三种类型之一。

遵从ECS范例使您能够在许多不同的实体中重复运用包括在组件中的功用,即使它们具有非常不同的承继联系。即使两个目标除了Entity之外没有共同的先人,您也能够将相同的组件增加到它们两者,并赋予它们相同的行为或功用。

从实体开端

实体是RealityKit的核心人物。您能够放入场景的任何目标,不管是否可见,都是实体,有必要是Entity的子孙。实体能够是3D模型、形状基元、灯光,甚至是不可见的项目,如声音发射器或触发体积。向实体增加组件以使它们存储与特定类型功用相关的附加状况。实体本身包括相对较少的特点:简直一切实体状况都存储在实体的组件上。

RealityKit供给了许多实体类型,用于表明不同类型的目标。例如,ModelEntity表明3D模型,比如从.usdz或.reality文件导入的模型。这些供给的实体本质上仅仅现已增加了某些组件的实体。例如,向Entity的一个实例增加ModelComponent将导致具有与ModelEntity相同功用的实体。

向实体增加组件

组件是您增加到实体的模块化构建块;它们标识体系将对哪些实体进行操作,并维护体系所依靠的每个实体的状况。组件能够包括逻辑,但将组件逻辑约束在验证其特点值或设置其初始状况的代码上。关于影响实体行为或或许在每一帧更改它们状况的任何逻辑,请运用体系。例如,要向实体增加可拜访性信息,请增加AccessibilityComponent,并用可拜访性体系所需的信息填充其字段,比如将VoiceOver读取的描述放入其标签特点。

请注意,一个实体一次只能持有一个特定类型的组件的副本。因此,例如,您不能向一个实体增加两个可拜访性组件。假如您向现已具有可拜访性组件的实体增加了一个新组件,则新组件将替换之前的组件。

创立体系以完成实体行为

体系(System)包括了RealityKit在每一帧调用以完成特定类型的实体行为或更新特定类型实体状况的代码。体系运用组件来存储其特定于实体的状况,并经过查找具有特定组件或组件组合的实体来查询要操作的实体。

例如,一个游戏或许有一个损害体系,监督并更新每个可受损或可被毁掉的实体的健康状况。体系一般与一个或多个组件一起作业,因此损害体系或许运用健康组件来盯梢每个实体遭到多少损害以及每个实体在被毁掉之前能够接受多少损害。它还或许与其他组件互动。例如,一个实体或许具有供给给该实体维护的护甲组件,损害体系还需求运用该组件中存储的状况。

每一帧,损害体系查询具有健康组件的实体,并依据应用程序的当前状况更新这些实体组件上的值。假如一个实体遭到了过多的损害,体系或许会触发特定的动画或将实体从场景中移除。

在体系中编写实体逻辑能够避免重复作业。运用传统的面向目标规划形式,这种类型的逻辑一般会存在于实体类上,往往会导致相同的核算多次履行,每个受影响的实体都要进行一次核算。不管这种核算潜在地影响多少个实体,体系只需求履行一次核算。

在场景中为实体施行体系

运用Entity Component System(ECS)能够在RealityKit场景中为实体界说和应用逻辑。体系特别适用于完成影响场景中多个实体的行为,例如用于表明鸟群的一群实体的集群行为。在传统的面向目标办法中,您经过在实体类上编写代码来完成实体的行为,该代码在每一帧中在该类的每个实例上运转。假如场景中有很多实体,这种办法或许效率低下,由于RealityKit有必要在每一帧中调用每个实体的更新办法。特别是假如一个实体的逻辑依靠于其他实体包括的状况,这一点尤为重要。

运用体系,RealityKit每帧仅调用每个体系的一个更新办法,而不是在每一帧中为每个实体调用一个更新办法。体系每帧迭代一切相关的实体,并依据需求更新它们的状况。以下是怎么完成自己的体系。

创立一个体系类

创立一个遵从System协议的类,完成两个办法:init(scene:)update(context:)。在init(scene:)中履行体系的设置,假如您的体系不需求任何设置,则增加一个空的完成。在update(context:)中增加运转体系所需的逻辑,RealityKit会主动在每一帧调用该办法。

class MySystem: System {
    required init(scene: Scene) {
        // 履行所需的初始化或设置。
    }
    func update(context: SceneUpdateContext) {
        // RealityKit会主动在每一帧调用此办法。
    }
}

警告:

由于RealityKit在每一帧中调用每个体系的update(context:)办法,请勿在该办法中履行不必要的作业。假如您的update(context:)办法花费很长时间才返回,或许会对应用程序的帧速率产生负面影响。

运用实体查询检索实体

为了有效地从场景中检索实体,请运用EntityQuery,您能够运用它来获取一切实体,或仅获取与您的体系相关的实体子集。虽然一些体系对场景中的每个实体进行操作,但大多数体系只对界说的子集进行操作,一般是依据实体的组件。例如,物理模仿体系仅需求在参加场景物理模仿的实体上操作,烘托体系仅需求在可见的实体上操作。要检索场景实体的子集,请创立一个包括您的条件的QueryPredicate,并在创立实体查询时将该谓词传递给初始化器。

将您的查询创立为体系的静态特点,除非您的查询条件在帧之间发生变化。假如条件在帧之间发生变化,请在update办法中创立查询。在update(context:)办法中运用实体查询,以迭代您的体系影响的一切实体。以下是一个体系怎么迭代具有特定组件的一切实体的示例。

struct MyComponent: Component {
    // 可选,能够在这里放置所需的状况。
}
class MySystem: System {
    // 界说一个查询,以返回一切具有MyComponent的实体。
    private static let query = EntityQuery(where: .has(MyComponent.self))
    required init(scene: Scene) { }
    func update(context: SceneUpdateContext) {
        context.scene.performQuery(Self.query).forEach { entity in
            // 在此对每个实体进行每帧更改。
        }
    }
}

在Reality Composer Pro中创立和增加组件

假如在项目中运用了Reality Composer Pro包,您能够在修改器中挑选实体,单击“增加组件”按钮,然后挑选“新建组件”选项来创立新的组件。这将为新组件创立一个Swift模板,然后您能够在Xcode中修改该模板。

要将自界说组件增加到实体上,请在您的Reality Composer Pro包中的文件中界说自界说组件。挑选要将自界说组件增加到的实体,单击“增加组件”按钮,然后挑选您的自界说组件的称号。然后,该实体将依据与查询自界说组件相同的体系做出响应和行为。

指定体系依靠联系

假如一个体系依靠于另一个体系以便正常运转,或者假如需求为多个体系指定更新顺序,请在体系中声明一个dependencies数组。要告知RealityKit一个依靠联系有必要在您的体系之前更新,请运用SystemDependency.before(_:)枚举案例,并将另一个体系作为参数传递。关于有必要在您的体系之后更新的依靠联系,请运用SystemDependency.before(_:)

class SystemB: RealityKit.System {
    static var dependencies: [SystemDependency] { 
        [.after(SystemA.self),        // 在SystemA之后运转SystemB。
         .before(SystemC.self)]       // 在SystemC之前运转SystemB。
     }
}

注册体系

您不需求手动创立System实例,RealityKit会为您创立,但前提是在显现应用程序的ARView之前经过调用其registerSystem()办法告知RealityKit您的体系。一旦您注册了体系,RealityKit会主动为每个活动场景创立体系的实例,然后在每一帧中反复调用其update(context:)办法。

MySystem.registerSystem()