【Unity】パルクールアクションの作り方!ウォールランなどのカッコいい動きを実装しよう

パルクールアクションの作り方 ゲーム開発

今回はタイトルのとおりで

Unityを使ったカッコいいパルクールアクションの作り方

をご紹介するという内容です。

パルクールとは簡単に言うと「走る・跳ぶ・登る等の動作を駆使して障害物を乗り越えるスポーツ」のこと。日本ではあまり馴染みがないかもしれませんが海外では絶大な人気があり、パルクール要素があるアクションゲームも大人気です。例えば

  • アサシンクリード
  • ウォッチドッグス
  • ダイイングライト
  • タイタンフォール

といったAAAタイトルもパルクール的なアクションがあることで有名ですよね。

それで海外ではそのようなアクションゲームを作っている開発者が多いらしく色々な情報が見つかるのですが、日本語の情報はほとんどない(というかググるとなぜか私が昔作ったアクションゲームが出てくる😅)という状態だったのでこれは記事を書いておいた方がいいなと思った次第です。

そこでここではパルクールアクションゲームを作るうえで特に重要と思われる

  1. ウォールラン(壁走り)
  2. 壁のぼり
  3. 段差乗り越え

の3つのアクションの作り方を解説していきますね。


※なお具体的なC#スクリプトを全部載せると内容がかなり複雑になってしまうので、今回はC#スクリプトは最小限にとどめ、作り方の手順をメインに紹介します。

ウォールラン(壁走り)

まずはパルクールゲームといえばコレ!というくらいポピュラーな「ウォールラン(壁走り)」の実装方法を見ていきましょう。完成サンプルは次のGIFのとおりです。

ウォールランの例

(画像クリックでGIF再生)

これを実装するために必要な処理は次のとおり。

  1. 接地判定
  2. 壁チェック
  3. 壁に沿って走る処理

接地判定

はじめに、ウォールランがどうのという前に接地判定が必要なのでその処理を用意しておきます。接地判定はいくつかやり方があり好きな方法を使っていただければOKだと思いますが、3Dアクションゲームの場合は個人的には下記のようにSphereCastを使うのが好きです。

[Min(0), Tooltip("接地判定用の中心点のオフセット")]
public float groundCheckOffsetY = 0.3f;
[Min(0), Tooltip("接地判定の距離")]
public float groundCheckDistance = 0;
[Min(0), Tooltip("接地判定の半径")]
public float groundCheckRadius = 0.2f;
[Tooltip("このレイヤーのオブジェクトにレイが当たった時に接地したと判定する")]
public LayerMask groundLayers = 0;

Vector3 groundNormal;
RaycastHit hit;

bool CheckGroundStatus()
{
    if (Physics.SphereCast(transform.position + Vector3.up * groundCheckOffsetY, groundCheckRadius, Vector3.down, out hit, .groundCheckOffsetY + groundCheckDistance, groundLayers, QueryTriggerInteraction.Ignore))
    {
        groundNormal = hit.normal;

        return true;
    }
    else
    {
        groundNormal = Vector3.zero;

        return false;
    }
}

これをUpdate関数内で呼び出して接地判定結果を変数にキャッシュしておき、キャラクターがいま地面の上に立っているのか、それとも空中にいるのかを確認できるようにしておきましょう。

ちなみに今回の内容には直接関係はないのですが、接地面の法線(ここではgroundNormal)をキャッシュしておくとキャラクターの移動処理に色々活用できて便利です。

壁チェック

次に壁を走るからには壁があるかどうかのチェックが必要です。次のように任意の方向に壁チェック用のRayを飛ばす関数を用意します。

[Tooltip("このレイヤーのオブジェクトにレイが当たった時に壁があると判定する")]
public LayerMask wallLayers = 0;

Vector3 wallNormal;

bool CheckWallStatus(float offsetY, float distance, Vector3 direction)
{
    if (Physics.Raycast(transform.position + Vector3.up * offsetY, direction, out hit, distance + capsuleCollider.radius, wallLayers, QueryTriggerInteraction.Ignore))
    {
        wallNormal = hit.normal;
        return true;
    }
    else
    {
        return false;
    }
}

ウォールランの場合は壁チェック用のRayをキャラクターの左右に出して、どちらか片方に壁があればウォールランを実行できるようにします。

壁に沿って走る処理

あとは壁があるときにFixedUpdate関数内で壁に沿って走る処理を実行すればOKです。ただし単純に壁に沿って走らせるだけだと不自然なので、ウォールランの実行中はキャラクターをZ方向に少し回転させて「壁を走ってる感」を出すのがポイントですね。

[Min(1)]
public float movementForce = 8;
[Min(0.1f)]
public float runForceMultiplier = 1.7f;

void WallRun(Vector3 direction, bool isLeft)
{
    rigidBody.AddForce(movementForce * runForceMultiplier * rigidBody.mass * direction.normalized, ForceMode.Force);

    RotateCharacterForWallRun(direction, isLeft);
}


[Range(0, 90)]
public float characterRotationZ = 20f;
[Min(0)]
public float rotationDuration = 0.15f;

void RotateCharacterForWallRun(Vector3 direction, bool isLeft)
{
    float angleZ = isLeft ? -characterRotationZ : characterRotationZ;

    transform.DOLocalRotateQuaternion(Quaternion.AngleAxis(angleZ, direction) * transform.localRotation, rotationDuration);
}

ちなみに上のコードではZ方向の回転処理にDOTweenを使用しています。DOTweenの使い方は下記のページで紹介しているので、興味のある方は併せてご覧いただければと思います。

【Unityアセット】DOTweenの使い方完全ガイド!超人気アセットを使いこなそう
今回はUnityユーザーの皆さんならおそらくご存じの神アセット「DOTween」の使い方を丁寧にご紹介するという内容です。 DOTweenは非常に人気が高いアセットなので既に持っていらっしゃる方も多いかと思いますが、正直なところ「使い方がよ...

壁のぼり

さて、お次は壁のぼりです。壁のぼりの場合は先ほどと同様に壁チェックをして、壁があればキャラクターを壁に沿って移動させるという形になります。完成サンプルは次のGIFのとおり。

壁のぼりの例

実装に必要な処理は次のとおりです。

  1. 壁チェック
  2. 壁に沿って移動する処理

※なお、上のサンプルのように三人称視点のキャラクターの場合は壁のぼり用のアニメーションを用意しておく必要があります。

壁チェック

まずはウォールランと同様に壁チェックが必要です。こちらはキャラクターの正面に向かって壁チェック用のRayを飛ばして、壁があれば壁のぼりを実行します。

壁に沿って移動する処理

次に壁に沿って移動する処理を書きます。

[Min(1)]
public float movementForce = 8;
[Min(0.1f)]
public float climbForceMultiplier = 0.5f;

Vector2 moveDirection;

void Climb(Vector2 move)
{
    moveDirection = Quaternion.LookRotation(-wallNormal) * move;

    rigidBody.velocity = movementForce * climbForceMultiplier * moveDirection;
}

上のClimb関数の引数moveはプレイヤーによる移動方向の入力です。この入力ベクトルが壁の法線方向を向くように回転させたものを移動方向とし、あとはそれを元にRigidbodyの速度を上書きすればOKです。

段差乗り越え

最後は段差の乗り越えです。完成サンプルは次のGIFのとおり。

段差乗り越えの例

これは壁チェックを行い、上方向の移動中に壁がなくなったら下の関数を実行するようにすればOKです。

[Min(0)]
public float wallCheckOffsetY = 0.1f;
[Min(0)]
public float climbstepDuration = 2;

void ClimbStep(Vector3 forward)
{
    transform.DOMove(thisTransform.position + wallCheckOffsetY * Vector3.up + capsuleCollider.radius * 2 * forward, climbstepDuration);
}

こちらも乗り越え移動の処理にDOTweenを使用しています。なお移動量については

  • キャラクターの足元から壁チェックの位置までの高さ分だけ上移動
  • キャラクターの直径分だけ前進

すれば上手く段差の上に乗ることができます。

おわりに

以上、パルクールアクションゲームの開発に必要なアクションの作り方を説明しました。

パルクール系のゲームはキャラクターの挙動の細かい部分まで気を配って作る必要があるためなかなか大変ですが、作れるとやはりカッコいいですし、プレイヤーさんにも楽しんでもらえると思います。ぜひ上記の内容を参考にしてかっこいいアクションゲームを作ってみてください。

この記事がUnityでのゲーム開発のお役に立てば幸いです。