【Unity】傾けた一人称カメラが壁をすり抜けないようにする

投稿者: | 2020-09-23

FPSキャラのカメラを横に傾ける #1FPSキャラのカメラを横に傾ける #2でFPSコントローラーのカメラを動かすと、壁を貫通して向こう側が見えてしまいます。

傾けていて壁に当たると自動でキャンセルするようにしてみます。まず、頭のカメラにコライダーとスクリプトを付けて、コライダーはIs Triggerにチェックをいれました。

スクリプトではカメラが壁に侵入したときに、FirstPersonControllerの静的メンバ変数をtrueにして、出たときにfalseにします。

using UnityEngine;

public class FPSCameraScript : MonoBehaviour
{
    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Untagged")
        {
            Debug.Log(other.tag);
            UnityStandardAssets.Characters.FirstPerson.FirstPersonController.headEnterWall = true;
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.tag == "Untagged") UnityStandardAssets.Characters.FirstPerson.FirstPersonController.headEnterWall = false;
    }
}

この変数はFirstPersonControllerクラスで定義しておきます。

public static bool headEnterWall;
bool previousHeadEnterWall;

// Update()
bool eD = Input.GetKeyDown(KeyCode.E);
bool eU = Input.GetKeyUp(KeyCode.E);
bool eG = Input.GetKey(KeyCode.E);
bool qD = Input.GetKeyDown(KeyCode.Q);
bool qU = Input.GetKeyUp(KeyCode.Q);
bool qG = Input.GetKey(KeyCode.Q);


if (headEnterWall)
{
    if (previousHeadEnterWall)
    {
        eD = false;
        eU = false;
        eG = false;
        qD = false;
        qU = false;
        qG = false;
    }
    else
    {
        if (eG) eU = true;
        if (qG) qU = true;

        eD = false;
        eG = false;
        qD = false;
        qG = false;
    }
}
else
{

}

previousHeadEnterWall = headEnterWall; // 値を保存

// 以下は前の記事と同じです

// 何もしていない
if (lean == 0)
{

    // 右へ
    if (!eU && eD && !(!qU && qD))
    {
        lean = 3;
    }

    // 左へ
    if (qD && !qU)
    {
        lean = 1;
    }

}
// 左へ移動
else if (lean == 1)
{
    // 回転
    m_MouseLook.leanAmount += maxAbsLeanRot / leanSpeed * Time.deltaTime * 10f;

    // 横移動
    leanPosX -= maxAbsLeanPosX / leanSpeed * Time.deltaTime * 10f;

    // 縦移動
    leanPosY -= maxAbsLeanPosY / leanSpeed * Time.deltaTime * 10f;


    /*
    if (m_MouseLook.leanAmount >= 0)
    {
        m_MouseLook.leanAmount += 30f * Time.deltaTime;
    }
    else {
        m_MouseLook.leanAmount += 80f * Time.deltaTime;

    }*/

    // 回転を止める
    if (m_MouseLook.leanAmount > maxAbsLeanRot)
    {
        m_MouseLook.leanAmount = maxAbsLeanRot;

    }

    // 移動を止める
    if (leanPosX < -maxAbsLeanPosX)
    {
        leanPosX = -maxAbsLeanPosX;
    }

    if (leanPosY < -maxAbsLeanPosY)
    {
        leanPosY = -maxAbsLeanPosY;
    }


    // 右へ
    if (!eU && eD)
    {
        lean = 3;
    }

    // 左から戻るへ
    if (qU && !(!eU && eD))
    {

        // 右へ
        if (eG)
        {
            lean = 3;

        }
        else if (m_MouseLook.leanAmount >= 0)
        {
            lean = 2;
        }
        // 右から戻るへ
        else if (m_MouseLook.leanAmount < 0)
        {
            lean = 4;
        }
    }

}
// 左から戻る
else if (lean == 2)
{

    m_MouseLook.leanAmount -= maxAbsLeanRot / leanSpeed * Time.deltaTime * 10f * BackswingRatio;

    leanPosX += maxAbsLeanPosX / leanSpeed * Time.deltaTime * 10f * BackswingRatio;

    leanPosY += maxAbsLeanPosY / leanSpeed * Time.deltaTime * 10f * BackswingRatio;

    if (m_MouseLook.leanAmount < 0f)
    {
        m_MouseLook.leanAmount = 0f;

        // lean = 0;
    }

    if (leanPosX > 0f)
    {
        leanPosX = 0f;
    }


    if (leanPosY > 0f)
    {
        leanPosY = 0f;

    }

    if (m_MouseLook.leanAmount <= 0f && leanPosX >= 0f && leanPosY >= 0f)
    {
        lean = 0;
    }

    // 右へ
    if (!eU && eD)
    {

        lean = 3;
    }

    // 左へ
    if (!qU && qD && !(!eU && eD))
    {
        lean = 1;
    }

}
// 右へ移動
else if (lean == 3)
{

    m_MouseLook.leanAmount -= maxAbsLeanRot / leanSpeed * Time.deltaTime * 10f;


    leanPosX += maxAbsLeanPosX / leanSpeed * Time.deltaTime * 10f;


    leanPosY -= maxAbsLeanPosY / leanSpeed * Time.deltaTime * 10f;

    /*
    if (m_MouseLook.leanAmount <= 0f)
    {
        m_MouseLook.leanAmount -= 30f * Time.deltaTime;
    }
    else
    {
        m_MouseLook.leanAmount -= 80f * Time.deltaTime;

    }*/

    // 傾きを止める
    if (m_MouseLook.leanAmount < -maxAbsLeanRot)
    {
        m_MouseLook.leanAmount = -maxAbsLeanRot;
    }

    // 移動を止める
    if (leanPosX > maxAbsLeanPosX)
    {
        leanPosX = maxAbsLeanPosX;
    }

    // 移動を止める
    if (leanPosY < -maxAbsLeanPosY)
    {
        leanPosY = -maxAbsLeanPosY;
    }

    // 左へ
    if (qD && !qU)
    {
        lean = 1;
    }

    // 右から戻るへ
    if (eU && !(!qU && qD))
    {
        lean = 4;

        // 左へ
        if (qG)
        {
            lean = 1;
        }
        // 右から戻るへ
        else if (m_MouseLook.leanAmount <= 0)
        {
            lean = 4;
        }
        // 左から戻るへ
        else if (m_MouseLook.leanAmount < 0)
        {
            lean = 2;
        }
    }
}
// 右から戻る
else if (lean == 4)
{

    m_MouseLook.leanAmount += maxAbsLeanRot / leanSpeed * Time.deltaTime * 10f * BackswingRatio;

    leanPosX -= maxAbsLeanPosX / leanSpeed * Time.deltaTime * 10f * BackswingRatio;

    leanPosY += maxAbsLeanPosY / leanSpeed * Time.deltaTime * 10f * BackswingRatio;



    if (m_MouseLook.leanAmount > 0f)
    {
        m_MouseLook.leanAmount = 0f;

        //lean = 0;
    }

    if (leanPosX < 0f)
    {
        leanPosX = 0f;
    }

    if (leanPosY > 0f)
    {
        leanPosY = 0f;

    }

    if (m_MouseLook.leanAmount >= 0f && leanPosX <= 0 && leanPosY >= 0f)
    {

        lean = 0;
    }


    if (!qU && qD)
    {
        lean = 1;
    }

    if (!eU && eD && !(!qU && qD))
    {
        lean = 3;
    }
}

まずキー入力を調べた後に、上で切り替える変数がtrueで、かつその変数の前のフレームでの値もtrueのときは、入力を全てfalseにします。

if (previousHeadEnterWall)
{
    eD = false;
    eU = false;
    eG = false;
    qD = false;
    qU = false;
    qG = false;
}

前のフレームでfalseのときは、壁に侵入した瞬間のフレームなので、キーが入力されていれば、GetKeyUpをtrueにして他はfalseにします。

else
{
    if (eG) eU = true;
    if (qG) qU = true;

    eD = false;
    eG = false;
    qD = false;
    qG = false;
}

そして、今の値を保存して次のフレームで使います。

previousHeadEnterWall = headEnterWall;

それ以降は上の記事と同じです。

これでカメラを傾けているときに壁に当たると、傾けるのをやめるようになりました。

無料ホラーゲームを作りました

コメントを残す

メールアドレスが公開されることはありません。