This document is about: QUANTUM 2
SWITCH TO

Materialization

概述

從一個Component PrototypeEntity Prototype來建立一個實體或元件執行個體的流程稱為 具體化

內嵌於地圖場景的場景原型的具體化,遵循與使用Frame.Create API的程式碼建立的執行個體的具體化的相同的規則及執行流程。

原型 vs 執行個體

元件執行個體及實體執行個體是遊戲狀態的一部分;換句話說,可以在運行階段操控它們。在DSL中宣告的元件用於生成它們的相應的Component Prototypes。程式碼生成的原型遵循命名慣例MyComponent_Prototype

Component PrototypesEntity Prototypes都是 資產;這意味著它們不是遊戲狀態的一部分,在運行階段不可變,並且在所有時間都必須對於所有客戶端而言完全相同。各個Component Prototype有一個ComponentPrototypeRef,其可使用 Frame.FindPrototype<MyComponentName_Prototype>(MyComponentPrototypeRef)來找出相應的資產。

元件原型

可以延伸一個Component Prototype以包含不直接用於具體化的資料。舉例而言,這允許在特定元件的執行個體之間共享資料,或從幀中排除唯讀資料,以保持遊戲狀態精簡。

程式碼生成的Component Prototypes是部分類別,其可輕易被延伸:

  1. 建立一個C#檔案名為 MyComponentName_Prototype.cs
  2. 將指令碼主體放入Quantum.Prototypes命名空間;
  3. 選擇性)新增using Quantum.Inspector;以存取Manual \ ECS頁面的Attributes章節中呈現的檢查器屬性。

之後可以新增額外的資料到Component Prototype資產,並且執行部分MaterializeUser()方法以新增自訂具體化邏輯。

例子

以下例子呈現了Vehicle元件的具體化,其出現於街機賽車範本之中。

Vehicle元件主要保有運行階段時計算的動態值。由於這些無法被初始化,在DSL中的元件定義使用這些參數上的ExcludeFromPrototype屬性,以從設計師可在Unity編輯器中操控的Vehicle_Prototype資產中排除它們。Nitro參數是唯一可編輯部分,以讓設計師決定一個特定的Vehicle要初始化多少Nitro。

C#

component Vehicle
{
    [ExcludeFromPrototype]
    ComponentPrototypeRef Prototype;

    [ExcludeFromPrototype]
    Byte Flags;
    [ExcludeFromPrototype]
    FP Speed;
    [ExcludeFromPrototype]
    FP ForwardSpeed;
    [ExcludeFromPrototype]
    FPVector3 EngineForce;
    [ExcludeFromPrototype]
    FP WheelTraction;

    [ExcludeFromPrototype]
    FPVector3 AvgNormal;

    [ExcludeFromPrototype]
    array<Wheel>[4] Wheels;

    FP Nitro;
}

延伸Vehicle_Prototype資產以提供設計師可自訂的唯讀參數。Vehicle_Prototype資產可因此保有針對一個特定車輛實體原型「類型」的所有執行個體的共享的值。在Vehicle元件中的Prototype參數屬於類型ComponentPrototypeRef,其是等同於AssetRef的元件特定。為了填入它,使用部分MaterializeUser()方法,以指派Vehicle_Prototype的參照。

C#

using Photon.Deterministic;
using Quantum.Inspector;
using System;

namespace Quantum.Prototypes
{
public unsafe partial class Vehicle_Prototype
{
    // PUBLIC METHODS

    [Header("Engine")]
    public FP EngineForwardForce = 130;
    public FP EngineBackwardForce = 120;
    public FPVector3 EngineForcePosition;
    public FP ApproximateMaxSpeed = 20;

    [Header("Hand Brake")]
    public FP HandBrakeStrength = 10;
    public FP HandBrakeTractionMultiplier = 1;

    [Header("Resistances")]
    public FP AirResistance = FP._0_02;
    public FP RollingResistance = FP._0_10 * 6;
    public FP DownForceFactor = 0;
    public FP TractionGripMultiplier = 10;
    public FP AirTractionDecreaseSpeed = FP._0_50;

    [Header("Axles")]
    public AxleSetup FrontAxle = new AxleSetup();
    public AxleSetup RearAxle = new AxleSetup();

    [Header("Nitro")]
    public FP MaxNitro = 100;
    public FP NitroForceMultiplier = 2;

    // PARTIAL METHODS
    partial void MaterializeUser(Frame frame, ref Vehicle result, in PrototypeMaterializationContext context)
    {
        result.Prototype = context.ComponentPrototypeRef;
    }

    [Serializable]
    public class AxleSetup
    {
        public FPVector3 PositionOffset;
        public FP Width = 1;
        public FP SpringForce = 120;
        public FP DampingForce = 175;
        public FP SuspensionLength = FP._0_10 * 6;
        public FP SuspensionOffset = -FP._0_25;
    }
}
}

Vehicle_Prototype中的參數保有必要的值,以計算元件執行個體中找到的動態值,該元件執行個體影響Vehicle元件附加的實體的行為。舉例而言,當玩家選取額外的Nitro,保存在Vehicle元件中的值被夾鉗到Vehicle_Prototype中找到的MaxNitro值。這將強制執行在取消同步懲罰下的限制,並保持遊戲狀態精簡。

C#

namespace Quantum
{
    public unsafe partial struct Vehicle
    {
        public void AddNitro(Frame frame, EntityRef entity, FP amount)
        {
            var prototype = frame.FindPrototype<Vehicle_Prototype>(Prototype);
            Nitro = FPMath.Clamp(Nitro + amount, 0, prototype.MaxNitro);
        }
    }
}

具體化順序

對於每個Entity Prototype,包含場景原型,具體化時按照順序執行以下步驟:

  1. 建立一個空的實體。
  2. 針對各個包含在Entity Prototype之中的Component Prototype
    1. 在堆疊上建立元件執行個體;
    2. Component Prototype被具體化到元件執行個體;
    3. 選擇性 )調用MaterializeUser();及,
    4. 元件被新增到實體,其觸發ISignalOnComponentAdded<MyComponent>信號。
  3. 針對各個已具體化實體,ISignalOnEntityPrototypeMaterialized被叫用。
    • 載入地圖/場景:在所有場景原型已經被具體化之後,針對所有實體及Entity Prototype配對,叫用信號。
    • Frame.Create()被建立:在原型已經被具體化之後,立即叫用信號。

Component Prototype具體化步驟以一個預先確定的順序來具體化預設元件。

C#

Transform2D
Transform3D
Transform2DVertical
PhysicsCollider2D
PhysicsBody2D
PhysicsCollider3D
PhysicsBody3D
PhysicsJoints2D
PhysicsJoints3D
PhysicsCallbacks2D
PhysicsCallbacks3D
CharacterController2D
CharacterController3D
NavMeshPathfinder
NavMeshSteeringAgent
NavMeshAvoidanceAgent
NavMeshAvoidanceObstacle
View
MapEntityLink

當所有預設元件已經被具體化,使用者定義的元件以字母順序被具體化。

C#

MyComponentAA
MyComponentBB
MyComponentCC
...
Back to top