はしごにレイが当たっているときにマウスクリックではしごを登り始め、登っているときはプレイヤーの回転を制限します。また、ななめのハシゴに沿って登れるようにします。
// カメラ
// はしごをのぼる
else if (hit.collider.tag == "Ladder" && hit.distance < 3f)
{
image.SetActive(true); // 手のマークを出す
if (Input.GetMouseButtonDown(0))
{
sc_fps.Warp(hit.transform); // はしごの前へワープする
image.SetActive(false); // 手のマークを消す
state = 4; // 登っている状態にする
}
}
// ---
// FirstPersonController
bool warp = false;
Vector3 warpPos;
Transform ladderTransform;
[SerializeField] float warpSpeed = 10f;
public void Warp(Transform t)
{
warp = true;
ladderTransform = t;
warpPos = t.GetChild(0).position;
m_MouseLook.Warp(t.GetChild(0));
}
前の記事では、はしごの子オブジェクトを使っていましたが、はしごのトランスフォームを、ワープするときの引数にしました。MouseLookのメソッドの引数へは子オブジェクトのトランスフォームを渡します。
プレイヤーがはしごに十分に接近するとワープが終了し、プレイヤーがハシゴに登っている状態になって、回転が制限されます。
Vector3 warpDir = warpPos - transform.position;
if (warpDir.magnitude <= 0.1f)
{
m_CollisionFlags = m_CharacterController.Move(warpDir);
StartCoroutine("EndWarp");
}
このときにキャラクターコントローラーのMoveメソッドで一気に指定の位置まで移動しますが、まだ回転値は指定の値まで達していないかもしれません。前の記事の方法ではプレイヤーが今向いている方向を基準にして回転の制限がかけられるので、指定の向きまで回転させてから回転の制限をかけたいです。
なので、ワープ終了のメソッドをコルーチンにしてその中の処理を時間差で行うようにしました。
IEnumerator EndWarp()
{
if (warp)
{
m_MouseLook.smooth = false; // 指定の向きにする
warp = false; // FirstPersonControllerのワープ終了
yield return null; // 1フレーム待つ
Climb(true, true, ladderTransform.up); // 回転に制限をかける
yield return null; // 1フレーム待つ
m_MouseLook.EndWarp(); // MouseLookのワープ終了
}
}
まずMouseLook.smoothをfalseにして、1フレームで一気に指定の方向を向くようにします。その後1フレーム待ってから回転を制限します。
回転の制限は、登っている状態にするメソッドの中で呼びます。
Vector3 climbingDir;
public void Climb(bool b, bool clamp, Vector3 dir = default)
{
m_IsClimbingPole = b;
climbingDir = dir;
ClampRotYAxis(clamp); // 回転を制限
}
この第三引数には、登っているときのプレイヤーの進行方向を渡します。すると、この方向に前後方向の入力から得られる値が掛け合わさったものが、キャラクターコントローラーの移動に使われます。
はしごから降りたいときは、第1.2引数をfalseにします。第三引数は省略できます。
/*
m_IsClimbingPole = false;
ClampRotYAxis(false);
*/
Climb(false, false);
引数を省略可能にするには既定値を持たせますが、Vector3.zeroなどにするとエラーがでます。ここではdefaultを使うといいそうです。参考:https://twitter.com/paperslothtech/status/786764110662742016
MouseLookではワープ中はインプットからキャラを回転させられないようにしますが、回転の制限と同時にワープを終了してしまうと、そのときにマウスを動かしていた場合、基準の向きも変わってしまうので、さらに1フレーム待ってからMouseLookのワープ終了の処理をします。
これでワープ中にマウスを動かしていても回転の範囲が同じになりました。
デフォルトでカメラをスムーズにしていても問題ありません。
MouseLookは、ワープ中にキー入力を受けないように変更しました。
// MouseLook
float yRot;
float xRot;
if (!warp)
{
yRot = /* ... */;
xRot = /* ... */;
// ...
}
次は、ハシゴの頂上に来たときにハシゴから降りられるようにしてみます。