This document is about: QUANTUM 3
SWITCH TO

4 - Player Entity

概述

在這一部分中,創建了一個玩家實體。它還提供了在Quantum中編寫遊戲程式碼的說明。

建造太空梭

在場景中創建一個新實體(Quantum > 2D > Quad Entity)。將其命名為AsteroidsShip,並從中移除網格篩選器和網格渲染器元件。

將盒碰撞器的延伸範圍調整為(0.7 0.9)。勾選PhysicsBody2D框,並將角阻力調整為6。

Create the Ship Entity
創建船實體。

接下來,為船創建模型。創建一個空的下層物件並將其命名為Model。為Model創建3個下層立方體遊戲物件。從每個立方體中移除盒碰撞器,並將每個立方體的旋轉設定為(0, 0, -45)

  • 將第一個立方體的位置設定為(0, 0, -0.542),並將其比例設定為(1.2, 0.7, 0.7)
  • 將第二個立方體的位置設定為(0, 0, 0.07),並將其比例設為(0.6, 0.6, 0.8)
  • 將第三個立方體的位置設定為(0, 0, 0.649),並將其比例設定為(0.3, 0.3, 0.5)
Create the Ship Model
為船創建模型。

遊戲程式碼

導航到專案視窗中的Assets/QuantumUser/Simulation。這是所有遊戲程式碼的位置。

按右鍵點擊Simulation資料夾。選擇Create > C# Script,並將其命名為AsteroidsShipSystem.cs

雙擊AsteroidsShipSystem.cs以在IDE中打開它。

打開文件後,移除所有程式碼並替換為:

C#

using UnityEngine.Scripting;

namespace Quantum.Asteroids
{
    [Preserve]
    public unsafe class AsteroidsShipSystem
    {
    }
}

命名空間是可選的,可以使用其他名稱。當不使用Quantum命名空間時,新增using Quantum;到頂部。

關鍵字unsafe允許在系統中使用不安全的程式碼,如指標。

Preserve屬性需要新增到所有Quantum系統中,以確保Unity在組建中包含它們,並在運行程式碼剝離時忽略它們。

ECS中編寫遊戲程式碼最常見的模式是讓系統迭代包含一組元件的實體集。使用Quantum ECS,這可以透過使用系統主執行緒篩選器來實現。

首先在AsteroidsShipSystem類別中新增一個篩選器結構:

C#

public struct Filter
{
    public EntityRef Entity;
    public Transform2D* Transform;
    public PhysicsBody2D* Body;
}

每個篩選器必須始終包含一個EntityRef欄位和任意數量的要篩選的元件指標欄位。始終使用篩選器中元件類型的指標。

要新增篩選器,請使系統繼承自SystemMainThreadFilter<AsteroidsShipSystem.Filter>類別:

C#

[Preserve]
public unsafe class AsteroidsShipSystem : SystemMainThreadFilter<AsteroidsShipSystem.Filter>

使用以下程式碼新增抽象Update函數的覆寫:

C#

public override void Update(Frame f, ref Filter filter)
{
    // note: pointer property access via -> instead of .
    filter.Body->AddForce(filter.Transform->Up);
}

對於篩選器中包含所有元件的每個實體,更新函數在每個幀上運行一次。幀參數表示系統運行的當前幀,並允許存取該特定幀的完整遊戲狀態。

該程式碼只是在船的Up方向上新增一個恒定的力。

但是,此程式碼尚未運行。為了系統運行,需要在系統設置資產中登錄。返回Unity並創建一個新的系統設置資產(按右鍵點擊資源資料夾,選擇Create > Quantum > Asset.. > SystemConfig)。將資產命名為AsteroidsSystemConfig

該設置已經在Entries清單中附帶了預先定義系統的清單。SystemConfig中的系統按照其中列出的確切順序執行。移除3D系統,如PhysicsSystem3DCullingSystem3D。同時移除Navigation系統,該系統用於導航網格尋路,但不用於此遊戲。

向清單中新增新條目。選擇Quantum.Asteroids > AsteroidsShipSystem作為System Type

SystemConfig Setup
新增AsteroidsShipSystem到SystemConfig。

前往場景中的QuantumDebugRunner物件,將系統設置放入Runtime Config > Systems Config下的欄位中。

停用重力

進入遊玩模式。請注意,船正在墜落,而不是向上移動。之所以如此,是因為重力仍然啟用。

有兩種方法可以停用物理體的重力。

  • PhysicsBody2DQuantumEntityPrototype中將Gravity Scale設定為0。
  • 在整個模擬中停用重力。

在這種情況下,使用後一種方法是因為小行星遊戲中沒有單向重力。

創建新的SimulationConfig asset(按右鍵點擊資源,然後選擇Create > Quantum > Asset.. > SimulationConfig)。將其命名為AsteroidsSimulationConfig。在Physics分頁中,將Gravity設定為(0,0,0)。

SimulationConfig資產包含Quantum模擬的許多可設置設定。在本教學中,預設值就足夠了。將AsteroidsSimulationConfig放入QuantumDebugRunnerSimulation Config欄位。

再次進入遊玩模式。船現在正確地緩慢向上漂浮。

輸入

按右鍵點擊QuantumUser/Simulation資料夾。選擇Create > Quantum > Qtn。將檔案命名為Input

Create the Input.qtn
創建Input.qtn。

Qtn檔案是使用Quantum域特定語言(DSL)的Quantum特定檔案。DSL的語法類似於C#。DSL用於定義實體元件資料和輸入資料。遊戲系統是用C#編寫的。

雙擊輸入檔案以在IDE中打開它,然後向其中新增以下內容:

C#

input {
    button Left;
    button Right;
    button Up;
    button Fire;
}

input是Quantum中的一個特殊關鍵字。Quantum只透過網路發送輸入,而不是遊戲狀態。這裡定義的Input是將透過網路發送並由遊戲模擬使用的資料。

注意: 輸入是每一個刷新發送的,用於頻繁變化並影響實時遊戲的輸入。例如移動和按鈕按下。對於不規則的罕見輸入,請改為使用命令

跳躍按鈕將用於讓玩家跳躍。按鈕類型是Quantum特定類型,應該用於所有按鈕輸入。不要對按鈕輸入使用布林值。它們消耗更多的頻寬。按鈕透過網路編碼為單個位元。

注意: 要在IDE中新增對DSL檔案的語法高亮顯示的支援,請按照指南此處進行操作。

更新AsteroidsShipSystem

返回Unity以便專案編譯。這將運行Quantum程式碼生成,使.qtn檔案中的Input在c#指令碼中可用。

現在輸入可用,打開AsteroidsShipSystem並新增一個新的UpdateShipMovement函數。

C#

private void UpdateShipMovement(Frame f, ref Filter filter, Input* input)
{
    FP shipAcceleration = 7;
    FP turnSpeed = 8;

    if (input->Up)
    {
        filter.Body->AddForce(filter.Transform->Up * shipAcceleration);
    }

    if (input->Left)
    {
        filter.Body->AddTorque(turnSpeed);
    }

    if (input->Right)
    {
        filter.Body->AddTorque(-turnSpeed);
    }

    filter.Body->AngularVelocity = FPMath.Clamp(filter.Body->AngularVelocity, -turnSpeed, turnSpeed);
}

FP類型與c#的float類型在Quantum中是等價的。Quantum使用固定點(FP)而不是浮點數來保證跨裝置的模擬是確定性的。

接下來,用以下程式碼替換Update函數中的程式碼。

C#

public override void Update(Frame f, ref Filter filter)
{
    // gets the input for player 0
    var input = f.GetPlayerInput(0);

    UpdateShipMovement(f, ref filter, input);
}

此函數獲取遊戲中玩家0的輸入,並根據輸入移動飛船。稍後,硬編碼的0將被替換,以便每艘飛船都由與其對應的玩家移動。

連接Unity輸入

QuantumUser/View資料夾中創建一個新的AsteroidsInput指令碼。View資料夾用於在Quantum的Unity端運行的程式碼,例如從Unity收集輸入事件並將其傳遞到Quantum模擬中。

在Unity項目中打開指令碼。此指令碼負責收集Unity輸入並將其傳遞到Quantum引擎。將指令碼中的程式碼替換為以下內容:

C#

using Photon.Deterministic;
using UnityEngine;

namespace Quantum.Asteroids
{
    public class AsteroidsInput : MonoBehaviour
    {
        private void OnEnable()
        {
            QuantumCallback.Subscribe(this, (CallbackPollInput callback) => PollInput(callback));
        }

        public void PollInput(CallbackPollInput callback)
        {
            Quantum.Input i = new Quantum.Input();

            // Note: Use GetKey() instead of GetKeyDown/Up. Quantum calculates up/down internally.
            i.Left = UnityEngine.Input.GetKey(KeyCode.A) || UnityEngine.Input.GetKey(KeyCode.LeftArrow);
            i.Right = UnityEngine.Input.GetKey(KeyCode.D) || UnityEngine.Input.GetKey(KeyCode.RightArrow);
            i.Up = UnityEngine.Input.GetKey(KeyCode.W) || UnityEngine.Input.GetKey(KeyCode.UpArrow);
            i.Fire = UnityEngine.Input.GetKey(KeyCode.Space);

            callback.SetInput(i, DeterministicInputFlags.Repeatable);
        }
    }
}

返回Unity並前往場景中的QuantumDebugInput物件。將其重命名為QuantumLocalInput,移除QuantumDebugInput指令碼,並改為新增新的AsteroidsInput指令碼。

接下來打開QuantumDebugRunner遊戲物件檢查器。在Local Players下新增一個代表玩家的條目。這將使Quantum為玩家0收集輸入。現時,0已硬編碼到SystemSetup中,玩家是場景的一部分。稍後,這將被每個玩家動態生成的玩家實體所取代。

Add the player
新增玩家。

玩家暱稱和虛擬人偶可用於將有關玩家的更多資訊傳遞到模擬中。

現在,當再次進入遊玩模式時,船可以使用WASD鍵移動。

Player movement in Unity editor
Back to top