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

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

ただいまの
回答率

87.37%

Unity C#で常にジャンプしているアクションゲームについて

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,048

score 27

アクションゲームを作っているのですが、当たった時の
挙動が想定したものと異なってしまいます。

床と当たった時に、上に飛ばしたいのです。
ただし、足場のBoxColliderの角にあたると
角度に応じて違う方向に飛んでしまいます。

角に当たった場合でも、上側に飛ばしたいです。

足場が細い部分に関しては、
キャラクターが埋まってしまったりもします。
こちらの改善方法などないでしょうか。

具体的な仕様とコードは下記となります。

■ ゲーム概要

・常にプレイヤーがジャンプしている。
→床と当たった瞬間にジャンプ

・ゲーム内には空中に足場があり、プレイヤーが下から当たったら通過できる。
→上から当たった場合は、さらにジャンプ

・ゲーム中、左右キーを押している間、押した方向に移動値を加算
→こちらは問題なし

・画面外に行ったら反対方向から出現
→こちらは問題なし

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//using UnityEngine.SceneManagement;

public class BallManager : MonoBehaviour {

    float speed = 4.5f;
    const float SPEED_MAX = 40.0f;
    const float JUMP_SPEED = 11.0f;
    bool buttonLeftFlag = false;
    bool buttonRightFlag = false;
    Vector3 scaleBall;
    Rigidbody rigidbody;
    SphereCollider sphereCollider;
    GameManager gameManager;

    // Start is called before the first frame update
    void Start() {

        scaleBall = transform.localScale;
        rigidbody = GetComponent<Rigidbody> ();
        sphereCollider = GetComponent<SphereCollider> ();
        gameManager = Camera.main.GetComponent<GameManager>();

    }

    // Update is called once per frame
    void Update() {

        // 左ボタン
        if(buttonLeftFlag || Input.GetKey (KeyCode.LeftArrow)){
            PressLeft();
        }

        // 右ボタン
        if(buttonRightFlag || Input.GetKey (KeyCode.RightArrow)){
            PressRight();
        }

        //Debug.Log(buttonLeftFlag + " " + buttonRightFlag);

        // 画面外の処理
        float screenX = gameManager.screen.x * 0.5f;
        if (transform.position.x > screenX + (scaleBall.x*0.5f)){
            transform.position = new Vector3(-screenX - (scaleBall.x*0.5f), transform.position.y, 0);
        } else if (transform.position.x < -screenX - (scaleBall.x*0.5f)){

            transform.position = new Vector3(screenX + (scaleBall.x*0.5f), transform.position.y, 0);
        }

        if(rigidbody.velocity.y < 0){
            sphereCollider.isTrigger = false;
        } else {
            sphereCollider.isTrigger = true;
        }

        Debug.Log(rigidbody.velocity.y);

        // 最大値の設定
        Vector3 velocity = rigidbody.velocity;
        if(velocity.y >= JUMP_SPEED){
            velocity.y = JUMP_SPEED;
            rigidbody.velocity = velocity;
        }

        //Debug.Log(Input.GetAxis("Vertical"));

    }

    //sphereに触れた時のメソッド
    private void OnCollisionEnter(Collision collision){
        //Y軸方向に常に同じ力を与える
        if(rigidbody.velocity.y <= 0){
            rigidbody.AddForce(Vector3.up * JUMP_SPEED, ForceMode.Impulse);
        }
    }

    // 押しっぱなし検出用
    public void PressLeftDown() {
        buttonLeftFlag = true;
    }

    public void PressLeftUp() {
        buttonLeftFlag = false;
    }

    public void PressRightDown() {
        buttonRightFlag = true;
    }

    public void PressRightUp() {
        buttonRightFlag = false;
    }

    void PressLeft() {
        Vector3 force = new Vector3 (-speed, 0.0f, 0.0f);
        if (Mathf.Abs(rigidbody.velocity.x) < SPEED_MAX ){
            rigidbody.AddForce(force); 
        }
    }

    void PressRight() {
        Vector3 force = new Vector3 (speed, 0.0f, 0.0f);
        if (Mathf.Abs(rigidbody.velocity.x) < SPEED_MAX ){
            rigidbody.AddForce(force);
        }
    }

    // 画面外にでたら
    void OnBecameInvisible() {
        //SceneManager.LoadScene ("GameScene"); 
        Debug.Log("GameOver");
    }

}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

0

角に当たった場合でも、上側に飛ばしたいです。

プログラムにはSphereColliderが適応されていますが、BoxColliderの質問でいいのですね。
角に当たった場合、違う方向に飛んでいくのは、Rigidbodyを使っている以上、どうしても現実世界の反射が適応されます。
BoxColliderの衝突判定にRigidbodyを使わず、OBBやAABBで判定を取った後、反射方向を自分でプログラムして下さい。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/03/23 18:55

    ご回答ありがとうございます。やはり仕様上仕方ないのですね。

    >>プログラムにはSphereColliderが適応されていますが、BoxColliderの質問でいいのですね。
    こちら誤解を招くソースですみません。キャラクターの当たり判定は球体なのでSphereColliderです。
    床が長方形のため、BoxColliderで判定をとっております。
    基本的に床にスクリプトがついておらず、キャラクターの球体にあるためSphereColliderを使用しておりました。

    以前、2Dゲームを作った時にAABBを使ってみたのですが、今回はOBBの方が良さそうなのでしょうか。
    色々と調べてみたのですが、raycast?というものを使うのが一般的なのでしょうか。

    こういったスクリプトを書いたことがないので、勉強させていただきたいです。

    キャンセル

  • 2020/03/24 09:49

    回転をしないBoxであれば、AABB。回転するBoxであれば、OBB。と言った様にオブジェクトの形や動きをしっかりと把握する必要があります。
    raycastは速度が速いオブジェクトに対しては全く使い物になりません。rayの仕様上仕方ないことですが重力落下程度でも時々バグったりします。

    一般的で明確的な答えはその分野にはありません。ようは出来てさえいれば正解な世界です。
    頑張って勉強して下さい。

    キャンセル

0

多分ですが、以下の部分でトリガーを切り替えてます
めり込んだ状態でトリガーをfalseにすると、
反発が発生して、お互いが弾け飛ぶ挙動になります

トリガーを切り替えるなら、お互いがめり込んでない時に切り替えてください

if(rigidbody.velocity.y < 0){
  sphereCollider.isTrigger = false;
} else {
  sphereCollider.isTrigger = true;
}

余談ですが、以下の行の処理では、右に一定速度以上になると
左を押しても減速しない状態になりますがそれはおかしくないですか?

Mathf.Abs(rigidbody.velocity.x) < SPEED_MAX

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/03/23 18:57

    ご回答ありがとうございます。
    めり込んでいないという判定は、if文で計算式で書かないとダメそうでしょうか。
    OnColliderEnterみたいな部分にフラグを用意して管理する形でしょうか。

    また余談についてもありがとうございます。完全にバグですね・・・。
    こちら最大移動量の制限として用意していたのですが、書き直します。

    キャンセル

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

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

関連した質問

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