This document is about: QUANTUM 1
SWITCH TO

Kinematic Character Controller (KCC)

はじめに

KCCは、Quantumゲームのキャラクターを制御するためのプレビルド機能です。2Dおよび3Dのワールドに対応し、すぐに使用できるAPIが付属しているため、キャラクターは簡単に様々なランドスケープ、山や階段などを移動できます。

静的オブジェクトと動的オブジェクトの両方の物理データに対して移動し、両方がキャラクターの動きをブロックして定義します。 移動するプラットフォームを処理し、他の物理オブジェクトとの衝突時にコールバックをトリガーします。

KCCとQuantum Transform コンポーネントを常に組み合わせる必要がありますが、DynamicBody とはハードカップリングされていません。KCCは独自の半径とオフセットを使用し、円(または球体)重複チェックのみを使用してその動きを計算します。

レイキャストによって無視されるのはこのためです。エンティティをレイキャストする必要がある場合は、DynamicBodyに対して実行する必要があります。

注意 このページでは、2Dと3Dの両方のKCCの使用法について説明しています。Quantumの物理にまだ慣れていない場合は、最初に物理マニュアル をご覧ください。

CharacterController コンポーネント

CharacterControllerコンポーネントをDSLのエンティティに追加します。この例では、TransformコンポーネントとDynamicBodyコンポーネントの両方の使用方法を示していますが、エンティティのセットアップにより適したコンポーネントの組み合わせを選択できます。

C#

// 2D KCC
entity Character2D[4]
{
  use Transform2D;
  use DynamicBody;
  use CharacterController2D; // this is the 2D KCC component
}

// 3D KCC
entity Character3D[4]
{
  use Transform3D;
  use DynamicBody3D;
  use CharacterController3D; // これは3D KCCコンポーネントです
}

エンティティを作成した後、コンポーネントを初期化する必要があります:パラメーターなしで Init() メソッドを呼び出すことでデフォルトのKCC設定を使用するか、オーバーロードメソッドを使用して使用する設定アセットを指定します。

C#

// 2D
character2D->CharacterController2D.Init();
character2D->CharacterController2D.Init(DB.FindAsset<CharacterController2DConfig>("My2DConfig"));

// 3D
character3D->CharacterController3D.Init();
character3D->CharacterController3D.Init(DB.FindAsset<CharacterController3DConfig>("My3DConfig"));

キャラクターコントローラー設定

デフォルトのKCC Configアセット(2Dと3Dの両方)は、 Assets/Resources/DB/Configsフォルダー内にあります。3D KCC設定は次のようになります:

KCC 3D Default Config

Create > Quantum > Assets > Physics > CharacterController2D/3D下のコンテキストメニューから独自のKCC設定アセットを作成します。

##Configフィールドへの簡単な説明

  • Offset は、エンティティの位置に基づいてKCCローカル位置を定義するために使用されます。Offsetフィールドを使用して、キャラクターの足にKCCを配置します。注意:KCCはキャラクターを移動するために使用されるので、キャラクターの体全体を覆う必要はありません。
  • Radius はキャラクターの境界を定義し、キャラクターの水平サイズを含む必要があります。これは、キャラクターがある方向に向かって動くことができるかどうか、または動きをブロックする壁があるかどうか、ステップ/スロープを登ったり滑ったりするかどうかを知るために使用されます。
  • Max Penetration は、キャラクターが他の物理オブジェクトを貫通するときの動きを滑らかにします。キャラクターがMax Penetrationを通過すると、そのキャラクターの位置にハードフィックスが適用され、正しくスナップされます。 この値をゼロに設定すると、修正が常に完全かつ即座に適用され、動きが滑らかにならない場合があります。
  • Extent は、衝突がプリエンプティブに検出される半径のフィールドを定義します。
  • Max Contacts を使用して、KCCで計算する接触点の数を選択します。通常は1で正常に機能し、最高のパフォーマンスを得られます。動きがぎくしゃくしている場合は、2に設定してみてください。パフォーマンスのオーバーヘッドは無視できます。
  • Air Control が「True」に切り替わり、KCCは地面に触れていないときに移動調整を実行できます。
  • Air Control Speed キャラクターが接地されていないときの動きの速さを定義します。
  • Acceleration キャラクターが加速する速さを定義します。
  • Base Jump Impulse KCC Jumpメソッドを呼び出すときのインパルスの強さを定義します。特定の値がJumpメソッドに渡されない場合、この値が使用されます。
  • Max Speed は、キャラクターの水平速度を制限します。
  • Gravity KCCに重力を適用します。重力の大きさと重力の正規化された値の2つの力に分割されます。
  • Max Slope キャラクターが上下に歩くことができるように急な傾斜がどの程度であるかを知るために使用される度単位の値。
  • Max Slope Speed Max Speedに似ていますが、動きのタイプが水平ではなく傾斜下降の場合の制限要因です。

CharacterController API

注意: 以下に示すAPIは3D APIに焦点を当てています。 ただし、2Dと3D KCC APIは非常に似ています。

プロパティとフィールド:

C#

public FP MaxSpeed;
public bool Grounded { get; }
public FP CurrentSpeed { get; }
public CharacterController3DConfig Config { get; set; }

ヒント: このフィールドは(Configアセットから読み取られた後)キャッシュされるため、実行中にMaxSpeed値を変更できます。 たとえば、ダッシュを実行するときに変更することができます。

The methods:

C#

// 初期化
public void Init(CharacterController3DConfig config = null);

// 動き
public static FPVector3 Move(void* entity, Transform3D* transform, CharacterController3D* kcc, FPVector3 velocity, DynamicScene3D scene, FP deltaTime, IKCCCallbacks callback = null);

public static CharacterController3DMovement ComputeRawMovement(void* entity, Transform3D* transform, CharacterController3D* kcc, FPVector3 velocity, DynamicScene3D scene, FP deltaTime, IKCCCallbacks callback = null);

// ジャンプ
public void Jump(FP? impulse, bool ignoreGrounded = false);

public void Jump(bool ignoreGrounded = false);

最も重要な概念は、Moveメソッドと ComputeRawMovementメソッドを使用してどのようにキャラクターを実際に移動するかです。

以下の2つのメソッドから選択する必要がります。

Move メソッド

現在の位置、速度、重力の追加、ジャンプ、傾斜などを考慮して、結果のキャラクターの位置を返します。すべては、Init()メソッドに渡された構成アセットに基づいています。これは、地形、メッシュコライダー、およびプリミティブを持つFPS / TPS / Actionゲームのプロトタイプ作成に非常に適しています。ただし、すでにすべてを計算し、最終的なFPVector3結果を返すため、動き自体をそれほど制御することはできません。移動変数をさらに制御したい場合は、後で説明する他の移動オプションを使用する必要があります。

フレームには既にMovement APIのラッパーが付属していることが重要です。キャラクターの移動方法に関するコードスニペットを次に示します。

C#

var characters = f.GetAllCharacters();
while (characters.Next())
{
  var character = characters.Current;
  var input = f.GetPlayerInput(character->PlayerRef);

  // 任意のJumpメソッド
  // メソッドにパラメーターとして渡される値はないため、使用されるジャンプインパルスは、構成アセットに含まれているものです
  if (input->Jump.WasPressed)
  {
    character->CharacterController3D.Jump();
  }

  // 動きベクトルを取得するフレームラッパー
  FPVector3 movement = f.CharacterController3D.Move((Entity*)character, input->Direction.XOY);

  // 動きがある場合は、それを変換コンポーネントに適用します
  if (movement != FPVector3.Zero)
  {
    character->Transform3D.Position += movement;
  }
}

Move()メソッドは、動きをすぐには適用しません。 Move()メソッドを呼び出して、結果をキャラクターの位置に適用しない場合、移動しません。

ヒント: フィルターを使用して、KCCコンポーネントを持つすべてのエンティティを反復処理することもできます。 詳細については、Migration NotesDev Logをご覧ください。

ComputeRawMovement メソッド

ComputeRawMovement()を使用してKCCでキャラクターを移動することもできます。キャラクタに動きを適用する方法を決定するために使用できる情報を受け取ります(たとえば、独自のカスタムステアリングを実装します)。 それはMove()メソッドによって内部的に使用されます

メソッドによって返される情報は次のとおりです:

C#

public struct CharacterController3DMovement
{
  public MovementType Type;
  public FPVector3 NearestNormal;
  public FPVector3 AvgNormal;
  public FPVector3 GroundNormal;
  public FPVector3 Tangent;
  public FPVector3 Correction;
  public FP Penetration;
  public Boolean Grounded;
  public Int32 Contacts;
}

コリジョンコールバック

KCCがコライダーとの交差を検出するたびに、コールバックが呼び出されます:

C#

  public interface IKCCCallbacks
  {
    bool OnCollision2D(CollisionInfo info);
    bool OnCollision3D(CollisionInfo info);
    void OnTrigger2D(CollisionInfo info);
    void OnTrigger3D(CollisionInfo info);
  }

コールバックを受け取り、独自のコードでその情報を使用するには、 IKCCCallbacksインターフェースを実装します。

重要: コリジョンコールバックがブール値を返します。これは、コリジョンを無視するかどうかを決定する方法です。falseを返すと、キャラクターはその物理オブジェクトを通過します。

コールバックの実装に加えて、移動メソッドは IKCCCallbacksオブジェクトも渡す必要があります。 コリジョンコールバックを使用したサンプルコードを次に示します。

C#

public unsafe class SampleSystem : SystemBase, Core.IKCCCallbacks
{
  public bool OnCollision2D(CollisionInfo info)
  {
    // コリジョン情報を読んで、これを無視するかどうかを決定する
    return true;
  }

  public bool OnCollision3D(CollisionInfo info)
  {
    // コリジョン情報を読んで、これを無視するかどうかを決定する
    return true;
  }

  public void OnTrigger2D(CollisionInfo info)
  {
  }

  public void OnTrigger3D(CollisionInfo info)
  {
  }

  public override void Update(Frame f)
  {
    // [...]
    // IKCCCallbacksを最後のパラメーターとして追加する(この場合、このシステム)
    var movement = f.CharacterController3D.Move((Entity*)character, input->Direction, this);
    // [...]
}
Back to top