ゴマちゃんフロンティア

気まぐれと勢いで作るUnityゲーム開発日記です。

【Unity】CharacterMotor使用時のキャラクター移動制限に関するちょっとした改良

time 2017/07/28

というわけで、最近「コアラのマーチ」にかなりハマっております。安価で多すぎず少なすぎずの絶妙な量、サクサク感と適度な甘さで食べやすく、手が汚れにくいのでデスクワークにもやさしいときました。残業続きな今日この頃、糖分を補給するのにこれ以上いいお菓子はないでしょう。
ちなみに女の子のほうは「ワルツちゃん」と言います。もちろん知ってますよね!

…ロッテの回し者のような前置きでしたが、今回は「CharacterMotor使用時の軸ごとの移動制限」に関するお話です。
以前「3D描画だけどゲーム的には2D」な移動制限をCharacterMotorで実現する方法を紹介しました。ただし内容は「Z軸をある一定値に固定する」というもので、完全に横スクロールアクション専用なものです。

せっかくの3D描画なのに終始同一ラインのみでは変化に欠けるので、進行方向に応じて切り替えられるようにしたいところです。実際はカメラアングル等の問題がクリアできていませんが、ひとまずCharacterMotorPlatformInputController使用時に「任意の方向を軸に2Dっぽく移動」について紹介します。

お話的には以下の記事の延長なので、本記事の内容が気になった方は見てみてください。

【Unity】CharacterMotor使用時のキャラクター移動を2Dに限定する

ここで扱う「CharacterMotor」と「PlatformInputController」は、フォーラムで投稿されていたC#版のものです。現在では古くなっている可能性もありますので、ご了承ください。

制限用フィールドの追加

Unityで「値を制限する」といえば、Mathf.Clamp()があります。「第1引数で指定した値を、第2引数~第3引数の間に収まる値で返す」という関数です。これでX軸とZ軸のベクトルを制限します。
制限する値は変数にして切り替えたいので、CharacterMotorPlatfornInputControllerのフィールドに変数を追加します。CharacterMotorの場合は以下のような感じです。

[Range(-1, 0)]
public float clamp_move_x_min;

[Range(0, 1)]
public float clamp_move_x_max;

[Range(-1, 0)]
public float clamp_move_z_min;

[Range(0, 1)]
public float clamp_move_z_max;

自分の場合は[Range]属性を付けて値の幅を制限していますが、このあたりはお好みで。

CharacterMotorの修正

今まではCharacterMotorの移動処理部分でZ軸を0に固定していましたが、今回は場面に合わせてX軸・Z軸の移動制限をかける必要があります。先程設定したフィールド変数とMathf.Clamp()で修正していきます。

Movementの修正

UpdateFunction()内のcontroller.Move()前にcurrentMovementOffsetを修正し、各軸の移動方向を制限します。「Move our character!」のコメントがあるあたりです。

// Reset variables that will be set by collision function
movingPlatform.hitPlatform = null;
groundNormal = Vector3.zero;

// Move our character!
currentMovementOffset.x = Mathf.Clamp(currentMovementOffset.x, clamp_move_x_min, clamp_move_x_max);
currentMovementOffset.z = Mathf.Clamp(currentMovementOffset.z, clamp_move_z_min, clamp_move_z_max);

movement.collisionFlags = controller.Move(currentMovementOffset);

movement.lastHitPoint = movement.hitPoint;
lastGroundNormal = groundNormal;

X軸は「シーンギズモの赤軸」、Z軸は「シーンギズモの青軸」の方向に対応し、最大値が矢印の方向、最小値は矢印の方向と逆側になります。

例えば「X軸にのみ移動可能」であれば、clamp_move_x_minを-1、clamp_move_x_maxを1に設定し、Z軸の2つは0に設定すればOKです。カメラアングルを調節した上で0.5に設定すれば斜めも大丈夫です。

MovingPlatform作用部分の修正

movingPlatformを有効にしている場合はmoveDistanceを変更します。Movement修正部分のちょっと上にあります。

Vector3 newGlobalPoint = movingPlatform.activePlatform.TransformPoint(movingPlatform.activeLocalPoint);
moveDistance = (newGlobalPoint - movingPlatform.activeGlobalPoint);

moveDistance.x = Mathf.Clamp(moveDistance.x, clamp_move_x_min, clamp_move_x_max);
moveDistance.z = Mathf.Clamp(moveDistance.z, clamp_move_z_min, clamp_move_z_max);

if(moveDistance != Vector3.zero)
    controller.Move(moveDistance);

PlatformInputControllerの修正

次に移動時の回転を制御するPlatformInputControllerを修正します。同じようにフィールドを用意し、回転前にnewForwardを変更します。

// Set rotation to the move direction   
if (autoRotate && directionVector.sqrMagnitude > 0.01)
{
    Vector3 newForward = ConstantSlerp(transform.forward, directionVector, maxRotationSpeed * Time.deltaTime);
    newForward = ProjectOntoPlane(newForward, transform.up);

    newForward.x = Mathf.Clamp(newForward.x, clamp_rotate_x_min, clamp_rotate_x_max);
    newForward.z = Mathf.Clamp(newForward.z, clamp_rotate_z_min, clamp_rotate_z_max);

    if (newForward != Vector3.zero) {
        transform.rotation = Quaternion.LookRotation(newForward, transform.up);
    }
}

制限する度合いによってはConstantSlerp()内のvalueも適度に変更する必要があります。自分は瞬時で振り向いてほしいので、valueを1に固定しています。

あとがき

そんなわけで、かなり短めながらCharacterMotorの移動制限に関するお話でした。
ネタ切れ気味な上に仕事が繁忙期のため更新が遅くなっていますが、月に何回かは話題を出していきたいと思いますので、今後ともよろしくお願いいたします!

スポンサーリンク

down

コメントする



ツイッター