This document is about: QUANTUM 2
SWITCH TO

Vehicular Combat

Level 4
Available in the Gaming Circle and Industries Circle
Circle

概要

KEO Vehicular Combat サンプルは、Quantumで作られた車両コンバットゲームです。このサンプルには2種類の車両(軽量バギーと重量のある8輪戦車)が含まれており、これらを使って進行中のフリーフォーオールデスマッチで戦います。

このサンプルはRedcatpigによって開発されました。Redcatpigが近日中にリリース予定のKEOをベースとしています。

テクニカルハイライト

  • 運転物理搭載の車両コントローラー
  • 多軸構成に対応
  • 動的サスペンションビューフォーミュラ
  • ダメージシステム
  • Hitscan武器システム

スクリーンショット

ダウンロード

多軸構成に対応

デフォルトでは、このサンプルは4つの車軸と8つの車輪(車軸あたり2つの車輪)をサポートしています。VehicleStateコンポーネントの固定配列サイズを大きくすることで、より多くの車軸と車輪を持つ車両を作成することができます; 単純に最大車両が持つ可能性がある車軸の最大数に設定します。

C#

component VehicleState {
    asset_ref<VehicleConfig> Config;
    DriveTrain DriveTrain;

    Byte AxleCount;
    array<AxleState>[4] Axles; // modify this value for support more axles

    [HideInInspector] FP TimeFlipped;
    [HideInInspector] FP TimeFalling;
    [HideInInspector] FP Fuel;
}

車軸のセットアップ

各車両について、その特定の車両のAxle Countを設定します。各アクセルが機能するにはAxleConfigWheelConfigSuspensionConfigTireConfigが必要です。

keo axle setup example
車軸のセットアップのサンプル。

車軸の設定

AxleConfigで車軸のオフセット(車両の中心/ピボットに対する相対的な位置)を設定できます。

keo axle config example
車軸の設定のサンプル。

各車軸はトラクションおよび/またはステアリングを適用できます。車軸が車両の後方にあり車輪もステアリングを適用する場合には(タンク車の場合など)、車輪に適切なステアリングを適用するためにInvertSteeringオプションを確認する必要があります。

C#

struct AxleState {
    asset_ref<AxleConfig> AxleConfig;

    asset_ref<WheelConfig> WheelConfig;
    asset_ref<SuspensionConfig> SuspensionConfig;
    asset_ref<TireConfig> TireConfig;

    [HideInInspector] FP SteerAngle;
    [HideInInspector] WheelState WheelL;
    [HideInInspector] WheelState WheelR;
}

運転アシスト

運転アシストセクションでは、各ステアリング車軸に対するステアリングの最大および最小角度を設定します。これによって、高速で運転する際のオーバーステアリングやコントロールを失うことを防ぎます。

keo drive assist example
運転アシスト。

サスペンション

Quantumシミュレーション内の車両物理の値を読むことで、サスペンションがUnity側で視覚化されます。これを担うクラスはAxleView.csです。

これは純粋なビジュアル表示のため、サスペンションのビジュアルはシミュレーションに反応しますが、サスペンション自体はシミュレーションの一部ではありません。このため、以下のセクションは完全にUnity側の表示とコードに関するものです。

動的サスペンションビュー

このサンプルに含まれるカスタムサスペンションビュー用の方式は、KEOの車両で作成されるサスペンションのタイプ特有のものです。ただし、ロジックは他のサスペンションタイプに適用できます。

サスペンションは以下から成ります:

  • 左/右車輪: 車両の動きに応じて、X軸上で回転する視覚車輪。
keo left-right wheel example
  • 左/右ピボット: このオブジェクトはサスペンション圧縮(Quantumシミュレーションから取得)に応じて設定されたY位置を取得し、ステアリングをシミュレーションするためにY軸上で回転します(車輪オブジェクトはピボットの子でなければなりません)。
keo left-right pivot example
  • 左/右の修正済みピボット: 車輪のY位置と同期されるオブジェクトで、サスペンションバーのすべての「内部」パーツを含みます (以下で説明します)。
keo left-right pivot fixed example

サスペンション方式

サスペンションバーは内側トップバー(A)、外側トップバー(B)、内側ボトム(C)、外側ボトム(D)で構成されています。

keo suspension bar example

ビジュアルを作動させる方式は以下のとおりです:

keo formula equation

この方式は車輪のY位置を取得し、それに応じて内側と外側のサスペンション部品を回転させて油圧バーの開閉をシミュレートするという考えにもとづいています。

そのためには、所定のサスペンションアームの開始角度(Alpha)が必要です。開始角度はトップバー(ケース #1)では常に0であり、ボトムバーでは測定する必要があります(下図のケース #2のAlphaを参照)。オフセット、すなわちバーが回転する位置からの最初のY距離も必要です(下図のケース #2のオフセット参照)。最後にワールドのX軸に完全に平行なときのサスペンションアームの長さ(Beta)を考慮する必要があります(ケース1のBetaを参照してください)。これらの値を測定するには、車両の作成に使用した3Dソフトを使用するのが最適です。

C#

LeftPivot.localRotation = Quaternion.Euler(0, axleState.WheelL.SteerAngle.AsFloat, 0);
RightPivot.localRotation = Quaternion.Euler(0, axleState.WheelR.SteerAngle.AsFloat, 0);

if (vehicleViewUpdateData.VehiclePhysicsBody->IsSleeping)
{
    return;
}

// update wheels suspension travel
var suspensionMaxTravel = _suspensionConfig.MaxTravel.AsFloat;

var leftSuspensionCompression = axleState.WheelL.Suspension.CompressionPrevious.AsFloat - suspensionMaxTravel;
var rightSuspensionCompression = axleState.WheelR.Suspension.CompressionPrevious.AsFloat - suspensionMaxTravel;

LeftPivot.localPosition = _leftPivotPosition + new Vector3(0, leftSuspensionCompression + _anchorOffset, 0) / Scale;
RightPivot.localPosition = _rightPivotPosition + new Vector3(0, rightSuspensionCompression + _anchorOffset, 0) / Scale;

LeftFixedPivot.localPosition = _leftFixedPivotPosition + new Vector3(0, leftSuspensionCompression + _anchorOffset, 0) / Scale;
RightFixedPivot.localPosition = _rightFixedPivotPosition + new Vector3(0, rightSuspensionCompression + _anchorOffset, 0) / Scale;

C#

float angleTop;
float angleBottom;

if (wheelLocalPos.y < 0)
{
    angleBottom = (Mathf.Atan((Mathf.Abs(wheelLocalPos.y) + _vehicleView.BottomOffset) / _vehicleView.BottomBeta) * 180 / Mathf.PI - _vehicleView.Alpha) * -1;
    angleTop = (Mathf.Atan((Mathf.Abs(wheelLocalPos.y) + _vehicleView.TopOffset) / _vehicleView.TopBeta) * 180 / Mathf.PI) * -1;
}
else
{
    angleBottom = Mathf.Atan((Mathf.Abs(wheelLocalPos.y) + _vehicleView.BottomOffset) / _vehicleView.BottomBeta) * 180 / Mathf.PI - _vehicleView.Alpha;
    angleTop = Mathf.Atan((Mathf.Abs(wheelLocalPos.y) + _vehicleView.TopOffset) / _vehicleView.TopBeta) * 180 / Mathf.PI;
}

if (leftSide)
{
    angleTop = angleTop < 0 ? Mathf.Abs(angleTop) : angleTop * -1;
    angleBottom = angleBottom < 0 ? Mathf.Abs(angleBottom) : angleBottom * -1;
}

suspensionInnerBottom.localRotation = Quaternion.Euler(new Vector3(0, 0, angleBottom));
suspensionInnerTop.localRotation = Quaternion.Euler(new Vector3(0, 0, angleTop));
suspensionOuterBottom.localRotation = Quaternion.Euler(new Vector3(0, 0, angleBottom));
suspensionOuterTop.localRotation = Quaternion.Euler(new Vector3(0, 0, angleTop));
keo formula diagram
Back to top