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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Q&A

解決済

1回答

3867閲覧

斜面を下がる時の平面ベクトルを求め方が知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

0グッド

1クリップ

投稿2020/02/16 03:42

編集2020/02/16 06:03

質問内容はタイトル通りですが、デバッグログを出力すると斜面の上る時と斜面を下る時でplaneVec.yの値が違います。つまりこのやり方では実装できないということがわかりました、では斜面を下る時の平面ベクトルはどうすれば求められるのでしょうか?

OnCollisionStay()関数部ですがカプセルコライダーと当たった場所を検出してそれの座標を使って平面ベクトルを求めてその値のY座標のプレイヤー移動変数のmove.yに入れて使っていますが ここで問題が発生していまして**「斜面を下がる時に下がりはしますが平面に沿って移動してくれません。」** の原因が知りたいです。

質問2、平面ベクトルは上手く求められてますでしょうか?

イメージ説明

using UnityEngine; public class Controller : MonoBehaviour { /* Ik 関係 Vector3 rightFootPos = new Vector3(0, 0, 0); Vector3 leftFootPos = new Vector3(0, 0, 0); Quaternion rightFootRot = new Quaternion(0, 0, 0, 0); Quaternion leftFootRot = new Quaternion(0, 0, 0, 0); bool isRightFootIK = false; bool isLeftFootIK = false; float RightIkWeight = 0; float LeftIkWeight = 0; Vector3 rayPositionOffset = new Vector3(0, 0, 0); float rayRange = 1.0f; float offset = 0.1f; */ private float input_h; private float input_v; private Vector3 move; private Rigidbody rb; private float walk_speed;//移動速度 private Animator ani;//移動速度 private Vector3 gravity; private bool isJump = false;//ジャンプしてるかどうかを管理する private Vector3 v; private bool isDush; private Vector3 move_direction;//移動方向 private bool c = false; // private CharacterController cc; private Vector3 planeVec;//平面ベクトル GameObject ground_ray; /*坂道計算*/ GameObject forward_ray; [SerializeField] float slope_range; [SerializeField] Vector3 slope_direc = new Vector3(0, 0, 0); [SerializeField] Vector3 slope_direc_b = new Vector3(0, 0, 0); GameObject contacts; // [SerializeField] Vector3 slope_pos; // Use this for initialization void Start() { ground_ray = GameObject.Find("GroundCheck"); forward_ray = GameObject.Find("SlopeCheck"); contacts = GameObject.Find("contacts"); // cc = GetComponent<CharacterController>(); forward_ray.transform.position = slope_pos + forward_ray.transform.position; walk_speed = 100; gravity = Vector3.zero; rb = GetComponent<Rigidbody>(); ani = GetComponent<Animator>(); } void Gravity_Mng()//ジャンプ管理 { } void Move_Mng() { input_h = Input.GetAxis("Horizontal"); input_v = Input.GetAxis("Vertical"); Vector3 move_z = new Vector3(); Vector3 move_x = new Vector3(); move_z = Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized * input_v; move_x = Camera.main.transform.right * input_h; move_direction = move_x + move_z; move_direction.y = 0; move.x = move_direction.x * walk_speed; move.z = move_direction.z * walk_speed; if (move_direction != Vector3.zero) { move_direction.y = 0; transform.rotation = Quaternion.LookRotation(move_direction.normalized); } } float getSpeed() { return Mathf.Abs(Mathf.Sqrt(move.x * move.x + move.z * move.z)); } // Update is called once per frame void Update() { // Debug.Log("move_direction: " + move_direction); // Debug.Log("move : " + move); // Debug.Log(" update move.y: " + move.y); } ////////////////////////////////////////////////////////////////////////////////////////////// void FixedUpdate() { Gravity_Mng(); Move_Mng(); // rb.AddForce(move.x, move.y, move.z); // Debug.Log("move_direction: " + move_direction); Debug.Log("move" + getSpeed()); /* if (move_direction != Vector3.zero){ move.y = planeVec.y; Debug.Log("v: " + planeVec.y); }else{ move.y = 0; } */ rb.AddForce(move.x,move.y,move.z); } ////////////////////////////////////////////////////////////////////////////////////////////// /**/ private void OnCollisionStay(Collision collision) { // Debug.Log("OnCollisionStay: " + collision.contacts[0].point); contacts.transform.position = collision.contacts[0].point; // Debug.Log(collision.contacts[0].point); // Debug.Log("あああああ"); Vector3 f = transform.forward; Vector3 vv = collision.contacts[0].normal; Vector3 dir = f - Vector3.Dot(f, vv) * vv; // f = dir.normalized * walk_speed;//y軸だけ使う // planeVec = dir.normalized * walk_speed; // planeVec = dir.normalized * getSpeed(); planeVec = dir.normalized * getSpeed(); move.y = planeVec.y; // Debug.Log("move.y: " + move.y); } private void OnCollisionExit(Collision c) { // move.y = -200.0f; } }

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

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

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

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

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

guest

回答1

0

ベストアンサー

こんにちは。

斜面に沿って物体を動かすのに使用するのは、おそらく平面ベクトルではなく法線ベクトルだと思います。
法線ベクトルとは平面の表から垂直に伸びたベクトルです。

法線ベクトルはOnCollisionStay等の引数にあるcollision内にあるのでそこから取得できます。

collision.contacts[0].normal

ですが、collision.contacts[]は配列になっていて接触した平面の情報が複数あるかもしれないので、その時は接触した平面の法線ベクトルを全て足せばいいかも?

取得した法線ベクトルはFixedUpdate内で使うので保持しておきましょう。
まずクラス内に法線ベクトルを保持する変数を宣言

private Vector3 groundNormal = Vecgtor3.zero;

OnCollsionStay内で接触した法線ベクトルを保持

groundNormal = collision.contacts[0].normal;

取得した法線ベクトルは平面の表から垂直に伸びているので、水平の平面の法線ベクトルは真上を向いています、傾いている平面の法線ベクトルは平面と同じ向きに傾いています。
なので、AddForceに設定するベクトルを今接触している平面の法線ベクトルと同じ向きに傾ければ、動かしたい物体を斜面に沿って動かせるようになるはずです。

ベクトルを傾けるにはQuaternionクラスを使うのが便利です。
QuaternionのStatic関数FromToRotationを使うと、1つ目の引数ベクトルから2つ目の引数ベクトルまで回転させるQuaternionを得る事ができます。今回は真上を向いたベクトルから保持しておいた法線ベクトルまで傾けるQuaternionが欲しいので、

Quaternion groundQuaternion = Quaternion.FromToRotation(Vector3.up, groundNormal);

で取得できます。

そして、Quaternionを使ってベクトルを傾ける方法は、

Vector3 moveAlongPlaneVector = groundQuaternion * move;

でOKです、moveAlongPlaneVectorに地面に沿った移動をするベクトルが入ります。
後はAddForceでこのベクトルで動かせば多分行けそう。

FixdeUpdate内でAddForceが行われていますが、その部分を書き換えて下さい。

Quaternion groundQuaternion = Quaternion.FromToRotation(Vector3.up, groundNormal); Vector3 moveAlongPlaneVector = groundQuaternion * move; rb.AddForce(moveAlongPlaneVector);

で行けるんじゃないかなぁ?

投稿2020/02/21 05:43

s_yossun

総合スコア14

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

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

退会済みユーザー

退会済みユーザー

2020/02/21 06:00

詳細にありがとうございます。 キャラクターコントローラーを使って実装しました。w
s_yossun

2020/02/21 06:09

キャラクターコントローラーを使えば地面に沿って動けるんですか、 問題が解決したなら良かったです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問