回答編集履歴
3
angularVelocity版での移動量が過剰だったため修正
test
CHANGED
@@ -204,12 +204,14 @@
|
|
204
204
|
|
205
205
|
var velocity = this.rigidbody.velocity;
|
206
206
|
|
207
|
-
|
207
|
+
Vector3.SmoothDamp(this.rigidbody.position, this.destination, ref velocity, 1.0f, 10.0f, Time.fixedDeltaTime);
|
208
208
|
|
209
209
|
// 非キネマティックに変えたので、MovePositionによる位置操作の結果が自動的にrigidbody.velocityに
|
210
210
|
|
211
211
|
// 反映されなくなるため、更新されたvelocityをrigidbody.velocityに再代入してやる
|
212
212
|
|
213
|
+
// SmoothDampの返り値は破棄し、rigidbody.velocity書き換えによってのみ移動させることでつじつまを合わせる
|
214
|
+
|
213
215
|
this.rigidbody.velocity = velocity;
|
214
216
|
|
215
217
|
|
2
angularVelocityについて追記
test
CHANGED
@@ -125,3 +125,121 @@
|
|
125
125
|
|
126
126
|
|
127
127
|

|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
### 追記
|
132
|
+
|
133
|
+
[angularVelocity](https://docs.unity3d.com/ScriptReference/Rigidbody-angularVelocity.html)の書き換えで回転させたい場合、オブジェクトを非キネマティックにしないとならないようです。
|
134
|
+
|
135
|
+
ですので、適宜重力を作用させなくしたり、他のオブジェクトから作用を受けないようにレイヤーを変更したりといった設定調整が必要かもしれません。
|
136
|
+
|
137
|
+
angularVelocity方式の例としては、こんな感じでどうでしょうか?
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
```C#
|
142
|
+
|
143
|
+
using UnityEngine;
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
[RequireComponent(typeof(Rigidbody), typeof(SphereCollider))]
|
148
|
+
|
149
|
+
public class NonKinematicSphereController : MonoBehaviour
|
150
|
+
|
151
|
+
{
|
152
|
+
|
153
|
+
private Vector3 destination;
|
154
|
+
|
155
|
+
private new Rigidbody rigidbody;
|
156
|
+
|
157
|
+
private SphereCollider sphereCollider;
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
private void Start()
|
162
|
+
|
163
|
+
{
|
164
|
+
|
165
|
+
this.rigidbody = this.GetComponent<Rigidbody>();
|
166
|
+
|
167
|
+
this.sphereCollider = this.GetComponent<SphereCollider>();
|
168
|
+
|
169
|
+
this.rigidbody.isKinematic = false; // 非キネマティックにする場合...
|
170
|
+
|
171
|
+
this.rigidbody.useGravity = false; // 重力を作用させなくする
|
172
|
+
|
173
|
+
}
|
174
|
+
|
175
|
+
|
176
|
+
|
177
|
+
private void Update()
|
178
|
+
|
179
|
+
{
|
180
|
+
|
181
|
+
var plane = new Plane(Vector3.up, this.rigidbody.position);
|
182
|
+
|
183
|
+
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
184
|
+
|
185
|
+
float rayDistance;
|
186
|
+
|
187
|
+
plane.Raycast(ray, out rayDistance);
|
188
|
+
|
189
|
+
if (rayDistance > 0.0f)
|
190
|
+
|
191
|
+
{
|
192
|
+
|
193
|
+
this.destination = ray.GetPoint(rayDistance);
|
194
|
+
|
195
|
+
}
|
196
|
+
|
197
|
+
}
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
private void FixedUpdate()
|
202
|
+
|
203
|
+
{
|
204
|
+
|
205
|
+
var velocity = this.rigidbody.velocity;
|
206
|
+
|
207
|
+
this.rigidbody.MovePosition(Vector3.SmoothDamp(this.rigidbody.position, this.destination, ref velocity, 1.0f, 10.0f, Time.fixedDeltaTime));
|
208
|
+
|
209
|
+
// 非キネマティックに変えたので、MovePositionによる位置操作の結果が自動的にrigidbody.velocityに
|
210
|
+
|
211
|
+
// 反映されなくなるため、更新されたvelocityをrigidbody.velocityに再代入してやる
|
212
|
+
|
213
|
+
this.rigidbody.velocity = velocity;
|
214
|
+
|
215
|
+
|
216
|
+
|
217
|
+
// 先に投稿したコードのtranslationをvelocityに置き換えると、得られる回転角は
|
218
|
+
|
219
|
+
// 1秒あたりの弧度法による回転量...つまり角速度の大きさとなる
|
220
|
+
|
221
|
+
// 回転軸も前回と同様の方法で求め、これが角速度ベクトルの向きとなる
|
222
|
+
|
223
|
+
// あとは求めた角速度ベクトル(向きaxis、大きさangularSpeed)を
|
224
|
+
|
225
|
+
// rigidbody.angularVelocityに代入すればいいはず
|
226
|
+
|
227
|
+
|
228
|
+
|
229
|
+
var speed = velocity.magnitude; // 速さ
|
230
|
+
|
231
|
+
var scaleXYZ = transform.lossyScale; // ワールド空間でのスケール推定値
|
232
|
+
|
233
|
+
var scale = Mathf.Max(scaleXYZ.x, scaleXYZ.y, scaleXYZ.z); // 各軸のうち最大のスケール
|
234
|
+
|
235
|
+
var angularSpeed = speed / (this.sphereCollider.radius * scale); // 角速度の大きさ
|
236
|
+
|
237
|
+
var axis = Vector3.Cross(Vector3.up, velocity).normalized; // 角速度の向き
|
238
|
+
|
239
|
+
this.rigidbody.angularVelocity = angularSpeed * axis;
|
240
|
+
|
241
|
+
}
|
242
|
+
|
243
|
+
}
|
244
|
+
|
245
|
+
```
|
1
球の半径がスケールを反映していなかったため修正
test
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
移動距離は`translation.magnitude`で、これを`distance`とします。
|
8
8
|
|
9
|
-
|
9
|
+
オブジェクトのスケールを`scale`とすると、コライダーの本来の半径が`sphereCollider.radius`ですので、球の半径は`this.sphereCollider.radius * scale`となり、弧度法による回転量は`distance / (this.sphereCollider.radius * scale)`となります。
|
10
10
|
|
11
11
|
|
12
12
|
|
@@ -78,13 +78,17 @@
|
|
78
78
|
|
79
79
|
}
|
80
80
|
|
81
|
-
|
81
|
+
|
82
82
|
|
83
83
|
var translation = this.rigidbody.velocity * Time.deltaTime; // 位置の変化量
|
84
84
|
|
85
85
|
var distance = translation.magnitude; // 移動した距離
|
86
86
|
|
87
|
+
var scaleXYZ = transform.lossyScale; // ワールド空間でのスケール推定値
|
88
|
+
|
89
|
+
var scale = Mathf.Max(scaleXYZ.x, scaleXYZ.y, scaleXYZ.z); // 各軸のうち最大のスケール
|
90
|
+
|
87
|
-
var angle = distance / this.sphereCollider.radius; // 球が回転するべき量
|
91
|
+
var angle = distance / (this.sphereCollider.radius * scale); // 球が回転するべき量
|
88
92
|
|
89
93
|
var axis = Vector3.Cross(Vector3.up, translation).normalized; // 球が回転するべき軸
|
90
94
|
|