回答編集履歴
1
垂直な崖を登れてしまう現象に対する修正案を追記
answer
CHANGED
|
@@ -80,4 +80,67 @@
|
|
|
80
80
|
|
|
81
81
|
なるべくささやかな修正で済ませたつもりですが、いかがでしょうかね?
|
|
82
82
|
|
|
83
|
-

|
|
83
|
+

|
|
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
|
+

|