回答編集履歴

3

angularVelocity版での移動量が過剰だったため修正

2018/07/14 22:21

投稿

Bongo
Bongo

スコア10807

test CHANGED
@@ -204,12 +204,14 @@
204
204
 
205
205
  var velocity = this.rigidbody.velocity;
206
206
 
207
- this.rigidbody.MovePosition(Vector3.SmoothDamp(this.rigidbody.position, this.destination, ref velocity, 1.0f, 10.0f, Time.fixedDeltaTime));
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について追記

2018/07/14 22:21

投稿

Bongo
Bongo

スコア10807

test CHANGED
@@ -125,3 +125,121 @@
125
125
 
126
126
 
127
127
  ![結果](8d1893de7a5b4be17271bf9f4da722a5.gif)
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

球の半径がスケールを反映していなかったため修正

2018/07/14 21:59

投稿

Bongo
Bongo

スコア10807

test CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  移動距離は`translation.magnitude`で、これを`distance`とします。
8
8
 
9
- の半径`sphereCollider.radius`ですので、弧度法による回転量は`distance / sphereCollider.radius`となります。
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