Unity-chanを標準の**「unity chan control script with rigidbody」**というスクリプトを用いて移動させたところ、80度程度の斜面でも登れてしまうことがわかりました。
45度以上の斜面は登れないようにしたいのですが、そのような設定は可能でしょうか。
※terrainで作成した地形を歩かせています。
「Charactor controller」コンポーネントだと「Slop Limit」などの斜面に関する設定項目があるのですが、
「unity chan control script with rigidbody」にはその設定項目がないためご質問させていただきました。
恐れ入りますが、ご教示の程よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
UnityChanControlScriptWithRgidBody
(クラス名とかコード内につづり間違いがポツポツ混じっているのがちょっと気になりますね...)には登れる斜面の限界だとかは特に設けられていないようです。そういった機能が必要でしたら改造を加えてやる必要がありそうですね。
まず、下記部分に...
lang
1 // 以下キャラクターコントローラ用パラメタ 2 // 前進速度 3 public float forwardSpeed = 7.0f; 4 // 後退速度 5 public float backwardSpeed = 2.0f; 6 // 旋回速度 7 public float rotateSpeed = 2.0f; 8 // ジャンプ威力 9 public float jumpPower = 3.0f;
フィールドを追加して下記のようにしました。
lang
1 // 以下キャラクターコントローラ用パラメタ 2 // 前進速度 3 public float forwardSpeed = 7.0f; 4 // 後退速度 5 public float backwardSpeed = 2.0f; 6 // 旋回速度 7 public float rotateSpeed = 2.0f; 8 // ジャンプ威力 9 public float jumpPower = 3.0f; 10 // 斜面が登りにくくなり始める角度 11 public float slopeLowerThreshold = 45.0f; 12 // 斜面が登れなくなる角度 13 public float slopeUpperThreshold = 60.0f;
また、下記移動部分を...
lang
1 // 上下のキー入力でキャラクターを移動させる 2 transform.localPosition += velocity * Time.fixedDeltaTime;
下記のように変更し、足元の地面の傾きに応じて移動力を落としてみました。
lang
1 // velocityの倍率を表す変数 2 float velocityMultiplier = 1.0f; 3 4 // キャラクターの原点(ユニティちゃんなら足元のはず)よりも少し上から 5 // 原点の少し下までレイキャストを行い... 6 if (Physics.Raycast(new Ray(transform.position + (Vector3.up * 0.125f), Vector3.down), out RaycastHit hit, 1.0f)) 7 { 8 // 足場が検出されたら、その法線を取得 9 Vector3 normal = hit.normal; 10 11 if (Mathf.Approximately(normal.y, 0.0f)) 12 { 13 // もし足場が垂直なら、velocityMultiplierを0倍に設定 14 // 真下へのレイキャストなので、こうなるケースはないはずですが 15 // 念のためゼロ除算のケースを考慮して条件分岐を設けました 16 velocityMultiplier = 0.0f; 17 } 18 else 19 { 20 // 傾き具合を調べ、velocityMultiplierを調整 21 Vector2 normalXZ = new Vector2(normal.x, normal.z); 22 Vector2 velocityXZ = new Vector2(velocity.x, velocity.z); 23 float slopeAngle = Mathf.Rad2Deg * Mathf.Atan2(-Vector2.Dot(normalXZ, velocityXZ) / normal.y, velocityXZ.magnitude); 24 float t = Mathf.Clamp01((slopeAngle - slopeLowerThreshold) / (slopeUpperThreshold - slopeLowerThreshold)); 25 velocityMultiplier = 1.0f - (t * t * (3.0f - (t * 2.0f))); 26 } 27 } 28 29 // velocityの大きさを調整 30 velocity *= velocityMultiplier; 31 32 33 // 上下のキー入力でキャラクターを移動させる 34 transform.localPosition += velocity * Time.fixedDeltaTime;
なるべくささやかな修正で済ませたつもりですが、いかがでしょうかね?
#追記
なるほど、ほぼ垂直に切り立った崖に突っ込んだ場合は...
- 崖のふもとにいる時は、レイキャスト時に足元の平坦な地面が検出され、傾いていないので移動力が制限されない。つまり条件的にご質問者さんが最初に試した時の80°の斜面と同じになって、崖のわずかな傾きによって少しずつ登れてしまう。
- 少しずつ崖を登っていって平坦部分から浮かんでいき、レイキャストがヒットしなくなると宙に浮いているのと同じ状況になる。空中にいる時に移動入力があった場合には移動力を制限しないようにしたため、やはり引き続き崖を登れてしまう。
といった状態になってしまったようですね。
代案として、まずスクリプト内に下記のようにimpulseSum
およびOnCollisionStay
を追加し...
lang
1 // 他のコライダーとの衝突によって受けた力積を 2 // OnCollisionStay内で足し合わせていくようにしました 3 Vector3 impulseSum; 4 5 void OnCollisionStay(Collision other) 6 { 7 impulseSum += other.impulse; 8 }
さらに最初の回答で提示しました移動部分を下記のように変更し、足の下へのレイキャストで法線を得る代わりに、衝突で受ける力積を法線と見なして傾き判定を行うというのはどうでしょうか。
lang
1 // velocityの倍率を表す変数 2 float velocityMultiplier = 1.0f; 3 4 // レイキャストに代わって、力積の総和の大きさで接地しているか 5 // (あるいは壁に触れているか)を判定し... 6 float impulseSumMagnitude = impulseSum.magnitude; 7 if (impulseSumMagnitude > 0.01f) 8 { 9 // 力積の方向を法線と見なすことにしました 10 Vector3 normal = impulseSum / impulseSumMagnitude; 11 12 if (Mathf.Approximately(normal.y, 0.0f)) 13 { 14 // もし足場が垂直なら、velocityMultiplierを0倍に設定 15 velocityMultiplier = 0.0f; 16 } 17 else 18 { 19 // 傾き具合を調べ、velocityMultiplierを調整 20 Vector2 normalXZ = new Vector2(normal.x, normal.z); 21 Vector2 velocityXZ = new Vector2(velocity.x, velocity.z); 22 float slopeAngle = Mathf.Rad2Deg * Mathf.Atan2(-Vector2.Dot(normalXZ, velocityXZ) / normal.y, velocityXZ.magnitude); 23 float t = Mathf.Clamp01((slopeAngle - slopeLowerThreshold) / (slopeUpperThreshold - slopeLowerThreshold)); 24 velocityMultiplier = 1.0f - (t * t * (3.0f - (t * 2.0f))); 25 } 26 } 27 28 // 判定の後は、impulseSumをゼロにリセットしておきます 29 impulseSum = Vector3.zero; 30 31 // velocityの大きさを調整 32 velocity *= velocityMultiplier; 33 34 // 上下のキー入力でキャラクターを移動させる 35 transform.localPosition += velocity * Time.fixedDeltaTime;
投稿2021/05/05 05:35
編集2021/05/05 21:49総合スコア10811
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/05/05 17:07
2021/05/05 18:28
2021/05/05 21:50
2021/05/06 09:35