質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

【Unity】接地判定・移動方向の切り替えが上手くいきません

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 170

前提・実現したいこと

横スクロール型アクションゲーム(3D)で、
敵が足場から落ちるときにゆっくり斜めに下がっていくのではなく、
ストンと下に落ちるようにしたいと思っています。

そこで、接地判定のトリガーを敵キャラの足元に配置し、
接地中は横方向、接地していないとき(落下中)は下方向に動くようにVelocityを切り替えようと考えました
(落下中は Vector3 (0, -5, 0)などにする)。

トリガーのスクリプトで接地(下記"OnGround")のtrue/falseを切り替え、
それを敵スクリプトが取得し、if構文でVelocityを切り替える仕組みを作ったのですが、
実行してみると、接地していない間も動きが変わりません。
さらに、以前は実行できていた左右の向き(enemyEulerAngles.y)による左右移動の切り替えも無効になってしまいました。
if構文を変えるなど、様々試してみたのですが解決できません。
もし改善点がお分かりでしたら、教えて頂けると嬉しいです。

該当のソースコード

【敵本体のスクリプト】

public class enemyMovement : MonoBehaviour
{
    private int layermask = 1 << 0 | 1 << 16;
    public Vector3 leftVelocity;//inspectorで(-4, 0, 0)に設定
    public Vector3 rightVelocity;//inspectorで(4, 0, 0)に設定
    public Vector3 leftFallVelocity;//inspectorで(-0.1, -5, 0)に設定
    public Vector3 rightFallVelocity;//inspectorで(0.1, -5, 0)に設定
    public GameObject GroundCheckTrigger;//inspectorでトリガーのオブジェクトを設定
    RaycastHit hit;

    void Start()
    {
        layermask = 1 << 0 | 1 << 16;
    }

    void Update()
    {
        Vector3 enemyEulerAngles = this.transform.localEulerAngles;
        Rigidbody enemyRB = this.transform.GetComponent<Rigidbody>();
        GroundChecker GroundCheck = GroundCheckTrigger.gameObject.GetComponent<GroundChecker>();

        if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.left), out hit, 1.3f, layermask))//レイキャストで、壁(layer 0)と敵(layer 16)へのヒットを判定
        {
            if (enemyEulerAngles.y == 0)//敵が左向きの場合
            {
                transform.eulerAngles = new Vector3(0, -180, 0);//敵を右向きにする
            }

            else//左向きでなければ
            {
                transform.eulerAngles = new Vector3(0, 0, 0);//右向きにする
            }
        }

        if (enemyEulerAngles.y == 0)//敵が左向きのとき
        {
            if (GroundCheck.OnGround = true)
            {
                enemyRB.velocity = leftVelocity;
            }

            else if (GroundCheck.OnGround = false)
            {
                enemyRB.velocity = leftFallVelocity;
            }
        }


        else if (enemyEulerAngles.y == -180)//敵が右向きのとき
        {
            if (GroundCheck.OnGround = true)
            {
                enemyRB.velocity = rightVelocity;
            }

            else if (GroundCheck.OnGround = false)
            {
                enemyRB.velocity = rightFallVelocity;
            }
        }
    }
}

【接地判定トリガーのスクリプト】

public class GroundChecker : MonoBehaviour
{
    public bool OnGround;

    void Start()
    {
        OnGround = false;
    }

    void OnTriggerEnter(Collider collision)
    {
        OnGround = true;
    }

    void OnTriggerExit(Collider collision)
    {
        OnGround = false;
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

回答ではありません。貼り付けられたコードがとてもじゃないが読める代物ではないため整形しています。

敵本体のスクリプト

public class enemyMovement : MonoBehaviour
{
    private int layermask = 1 << 0 | 1 << 16;
    public Vector3 leftVelocity;
    public Vector3 rightVelocity;
    public Vector3 fallVelocity;
    public GameObject GroundCheckTrigger;
    RaycastHit hit;

    void Start()
    {
        layermask = 1 << 0 | 1 << 16;
    }

    void Update()
    {
        Vector3 enemyEulerAngles = this.transform.localEulerAngles;
        Rigidbody enemyRB = this.transform.GetComponent<Rigidbody>();
        GroundChecker GroundCheck = GroundCheckTrigger.gameObject.GetComponent<GroundChecker>();

        if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.left), out hit, 1.3f, layermask))
        {
            if (enemyEulerAngles.y == 0)
            {
                transform.eulerAngles = new Vector3(0, -180, 0);
            }

            else
            {
                transform.eulerAngles = new Vector3(0, 0, 0);
            }
        }

        if (enemyEulerAngles.y == 0)
        {
            if (GroundCheck.OnGround = true)
            {
                enemyRB.velocity = leftVelocity;
            }

            else if (GroundCheck.OnGround = false)
            {
                enemyRB.velocity = leftFallVelocity;
            }
        }

        else if (enemyEulerAngles.y == -180)
        {
            if (GroundCheck.OnGround = true)
            {
                enemyRB.velocity = rightVelocity;
            }

            else if (GroundCheck.OnGround = false)
            {
                enemyRB.velocity = rightFallVelocity;
            }
        }
    }
}

接地判定トリガーのスクリプト

public class GroundChecker : MonoBehaviour
{
    public bool OnGround;

    void Start()
    {
        OnGround = false;
    }

    void OnTriggerEnter(Collider collision)
    {
        OnGround = true;
    }

    void OnTriggerExit(Collider collision)
    {
        OnGround = false;
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/11 19:04

    enemyEulerAnglesについては、(0.0, 0.0, 0.0)だったので、角度は問題なかったようです。

    キャンセル

  • 2020/07/11 19:07

    > AddForceも試してみたのですが、どんどん加速してしまうため、一定速度を保つためにVelocityで移動を制御しています。

    速度が上がり過ぎたら AddForce しないように制御すればよいでしょう。現状の力学的に不自然な制御よりは簡単だと思います。

    キャンセル

  • 2020/07/11 22:47

    色々な助言、ありがとうございます。とても勉強になりました。
    接地判定に関してどこがおかしいのか最終的に分からなかったので、
    逃げの手法ではありますが、onCollisionStay/onCollisionExitで接地中/非接地中の挙動を分けました。
    別オブジェクトをトリガーにする手法はもう少し知識が必要のようなので、改めて勉強します。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る