質問するログイン新規登録

回答編集履歴

1

垂直な崖を登れてしまう現象に対する修正案を追記

2021/05/05 21:49

投稿

Bongo
Bongo

スコア10816

answer CHANGED
@@ -80,4 +80,67 @@
80
80
 
81
81
  なるべくささやかな修正で済ませたつもりですが、いかがでしょうかね?
82
82
 
83
- ![図](3cf3f33b832a67fafaec2ddf9609a44d.gif)
83
+ ![図](3cf3f33b832a67fafaec2ddf9609a44d.gif)
84
+
85
+ #追記
86
+
87
+ なるほど、ほぼ垂直に切り立った崖に突っ込んだ場合は...
88
+
89
+ - 崖のふもとにいる時は、レイキャスト時に足元の平坦な地面が検出され、傾いていないので移動力が制限されない。つまり条件的にご質問者さんが最初に試した時の80°の斜面と同じになって、崖のわずかな傾きによって少しずつ登れてしまう。
90
+ - 少しずつ崖を登っていって平坦部分から浮かんでいき、レイキャストがヒットしなくなると宙に浮いているのと同じ状況になる。空中にいる時に移動入力があった場合には移動力を制限しないようにしたため、やはり引き続き崖を登れてしまう。
91
+
92
+ といった状態になってしまったようですね。
93
+ 代案として、まずスクリプト内に下記のように`impulseSum`および`OnCollisionStay`を追加し...
94
+
95
+ ```lang-csharp
96
+ // 他のコライダーとの衝突によって受けた力積を
97
+ // OnCollisionStay内で足し合わせていくようにしました
98
+ Vector3 impulseSum;
99
+
100
+ void OnCollisionStay(Collision other)
101
+ {
102
+ impulseSum += other.impulse;
103
+ }
104
+ ```
105
+
106
+ さらに最初の回答で提示しました移動部分を下記のように変更し、足の下へのレイキャストで法線を得る代わりに、衝突で受ける力積を法線と見なして傾き判定を行うというのはどうでしょうか。
107
+
108
+ ```lang-csharp
109
+ // velocityの倍率を表す変数
110
+ float velocityMultiplier = 1.0f;
111
+
112
+ // レイキャストに代わって、力積の総和の大きさで接地しているか
113
+ // (あるいは壁に触れているか)を判定し...
114
+ float impulseSumMagnitude = impulseSum.magnitude;
115
+ if (impulseSumMagnitude > 0.01f)
116
+ {
117
+ // 力積の方向を法線と見なすことにしました
118
+ Vector3 normal = impulseSum / impulseSumMagnitude;
119
+
120
+ if (Mathf.Approximately(normal.y, 0.0f))
121
+ {
122
+ // もし足場が垂直なら、velocityMultiplierを0倍に設定
123
+ velocityMultiplier = 0.0f;
124
+ }
125
+ else
126
+ {
127
+ // 傾き具合を調べ、velocityMultiplierを調整
128
+ Vector2 normalXZ = new Vector2(normal.x, normal.z);
129
+ Vector2 velocityXZ = new Vector2(velocity.x, velocity.z);
130
+ float slopeAngle = Mathf.Rad2Deg * Mathf.Atan2(-Vector2.Dot(normalXZ, velocityXZ) / normal.y, velocityXZ.magnitude);
131
+ float t = Mathf.Clamp01((slopeAngle - slopeLowerThreshold) / (slopeUpperThreshold - slopeLowerThreshold));
132
+ velocityMultiplier = 1.0f - (t * t * (3.0f - (t * 2.0f)));
133
+ }
134
+ }
135
+
136
+ // 判定の後は、impulseSumをゼロにリセットしておきます
137
+ impulseSum = Vector3.zero;
138
+
139
+ // velocityの大きさを調整
140
+ velocity *= velocityMultiplier;
141
+
142
+ // 上下のキー入力でキャラクターを移動させる
143
+ transform.localPosition += velocity * Time.fixedDeltaTime;
144
+ ```
145
+
146
+ ![図2](c9195bab7724ddcf05de1841af1e3334.gif)