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

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

新規登録して質問してみよう
ただいま回答率
85.49%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

2162閲覧

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

momiji0210

総合スコア60

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/03/22 18:34

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

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

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

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

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

■ ゲーム概要

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

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

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

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

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4//using UnityEngine.SceneManagement; 5 6public class BallManager : MonoBehaviour { 7 8 float speed = 4.5f; 9 const float SPEED_MAX = 40.0f; 10 const float JUMP_SPEED = 11.0f; 11 bool buttonLeftFlag = false; 12 bool buttonRightFlag = false; 13 Vector3 scaleBall; 14 Rigidbody rigidbody; 15 SphereCollider sphereCollider; 16 GameManager gameManager; 17 18 // Start is called before the first frame update 19 void Start() { 20 21 scaleBall = transform.localScale; 22 rigidbody = GetComponent<Rigidbody> (); 23 sphereCollider = GetComponent<SphereCollider> (); 24 gameManager = Camera.main.GetComponent<GameManager>(); 25 26 } 27 28 // Update is called once per frame 29 void Update() { 30 31 // 左ボタン 32 if(buttonLeftFlag || Input.GetKey (KeyCode.LeftArrow)){ 33 PressLeft(); 34 } 35 36 // 右ボタン 37 if(buttonRightFlag || Input.GetKey (KeyCode.RightArrow)){ 38 PressRight(); 39 } 40 41 //Debug.Log(buttonLeftFlag + " " + buttonRightFlag); 42 43 // 画面外の処理 44 float screenX = gameManager.screen.x * 0.5f; 45 if (transform.position.x > screenX + (scaleBall.x*0.5f)){ 46 transform.position = new Vector3(-screenX - (scaleBall.x*0.5f), transform.position.y, 0); 47 } else if (transform.position.x < -screenX - (scaleBall.x*0.5f)){ 48 49 transform.position = new Vector3(screenX + (scaleBall.x*0.5f), transform.position.y, 0); 50 } 51 52 if(rigidbody.velocity.y < 0){ 53 sphereCollider.isTrigger = false; 54 } else { 55 sphereCollider.isTrigger = true; 56 } 57 58 Debug.Log(rigidbody.velocity.y); 59 60 // 最大値の設定 61 Vector3 velocity = rigidbody.velocity; 62 if(velocity.y >= JUMP_SPEED){ 63 velocity.y = JUMP_SPEED; 64 rigidbody.velocity = velocity; 65 } 66 67 //Debug.Log(Input.GetAxis("Vertical")); 68 69 } 70 71 //sphereに触れた時のメソッド 72 private void OnCollisionEnter(Collision collision){ 73 //Y軸方向に常に同じ力を与える 74 if(rigidbody.velocity.y <= 0){ 75 rigidbody.AddForce(Vector3.up * JUMP_SPEED, ForceMode.Impulse); 76 } 77 } 78 79 // 押しっぱなし検出用 80 public void PressLeftDown() { 81 buttonLeftFlag = true; 82 } 83 84 public void PressLeftUp() { 85 buttonLeftFlag = false; 86 } 87 88 public void PressRightDown() { 89 buttonRightFlag = true; 90 } 91 92 public void PressRightUp() { 93 buttonRightFlag = false; 94 } 95 96 void PressLeft() { 97 Vector3 force = new Vector3 (-speed, 0.0f, 0.0f); 98 if (Mathf.Abs(rigidbody.velocity.x) < SPEED_MAX ){ 99 rigidbody.AddForce(force); 100 } 101 } 102 103 void PressRight() { 104 Vector3 force = new Vector3 (speed, 0.0f, 0.0f); 105 if (Mathf.Abs(rigidbody.velocity.x) < SPEED_MAX ){ 106 rigidbody.AddForce(force); 107 } 108 } 109 110 // 画面外にでたら 111 void OnBecameInvisible() { 112 //SceneManager.LoadScene ("GameScene"); 113 Debug.Log("GameOver"); 114 } 115 116}

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

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

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

投稿2020/03/23 02:30

stdio

総合スコア3307

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

momiji0210

2020/03/23 09:55

ご回答ありがとうございます。やはり仕様上仕方ないのですね。 >>プログラムにはSphereColliderが適応されていますが、BoxColliderの質問でいいのですね。 こちら誤解を招くソースですみません。キャラクターの当たり判定は球体なのでSphereColliderです。 床が長方形のため、BoxColliderで判定をとっております。 基本的に床にスクリプトがついておらず、キャラクターの球体にあるためSphereColliderを使用しておりました。 以前、2Dゲームを作った時にAABBを使ってみたのですが、今回はOBBの方が良さそうなのでしょうか。 色々と調べてみたのですが、raycast?というものを使うのが一般的なのでしょうか。 こういったスクリプトを書いたことがないので、勉強させていただきたいです。
stdio

2020/03/24 00:49

回転をしないBoxであれば、AABB。回転するBoxであれば、OBB。と言った様にオブジェクトの形や動きをしっかりと把握する必要があります。 raycastは速度が速いオブジェクトに対しては全く使い物になりません。rayの仕様上仕方ないことですが重力落下程度でも時々バグったりします。 一般的で明確的な答えはその分野にはありません。ようは出来てさえいれば正解な世界です。 頑張って勉強して下さい。
guest

0

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

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

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

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

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

投稿2020/03/23 02:18

izmktr

総合スコア2856

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

momiji0210

2020/03/23 09:57

ご回答ありがとうございます。 めり込んでいないという判定は、if文で計算式で書かないとダメそうでしょうか。 OnColliderEnterみたいな部分にフラグを用意して管理する形でしょうか。 また余談についてもありがとうございます。完全にバグですね・・・。 こちら最大移動量の制限として用意していたのですが、書き直します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問