回答編集履歴
3
angularVelocity版での移動量が過剰だったため修正
answer
CHANGED
@@ -101,9 +101,10 @@
|
|
101
101
|
private void FixedUpdate()
|
102
102
|
{
|
103
103
|
var velocity = this.rigidbody.velocity;
|
104
|
-
|
104
|
+
Vector3.SmoothDamp(this.rigidbody.position, this.destination, ref velocity, 1.0f, 10.0f, Time.fixedDeltaTime);
|
105
105
|
// 非キネマティックに変えたので、MovePositionによる位置操作の結果が自動的にrigidbody.velocityに
|
106
106
|
// 反映されなくなるため、更新されたvelocityをrigidbody.velocityに再代入してやる
|
107
|
+
// SmoothDampの返り値は破棄し、rigidbody.velocity書き換えによってのみ移動させることでつじつまを合わせる
|
107
108
|
this.rigidbody.velocity = velocity;
|
108
109
|
|
109
110
|
// 先に投稿したコードのtranslationをvelocityに置き換えると、得られる回転角は
|
2
angularVelocityについて追記
answer
CHANGED
@@ -61,4 +61,63 @@
|
|
61
61
|
|
62
62
|
このような動きになりました。見やすくするため地面オブジェクトを配置しましたが、動きはスクリプトで制御されているので、球が地面から外れても落下しません。
|
63
63
|
|
64
|
-

|
64
|
+

|
65
|
+
|
66
|
+
### 追記
|
67
|
+
[angularVelocity](https://docs.unity3d.com/ScriptReference/Rigidbody-angularVelocity.html)の書き換えで回転させたい場合、オブジェクトを非キネマティックにしないとならないようです。
|
68
|
+
ですので、適宜重力を作用させなくしたり、他のオブジェクトから作用を受けないようにレイヤーを変更したりといった設定調整が必要かもしれません。
|
69
|
+
angularVelocity方式の例としては、こんな感じでどうでしょうか?
|
70
|
+
|
71
|
+
```C#
|
72
|
+
using UnityEngine;
|
73
|
+
|
74
|
+
[RequireComponent(typeof(Rigidbody), typeof(SphereCollider))]
|
75
|
+
public class NonKinematicSphereController : MonoBehaviour
|
76
|
+
{
|
77
|
+
private Vector3 destination;
|
78
|
+
private new Rigidbody rigidbody;
|
79
|
+
private SphereCollider sphereCollider;
|
80
|
+
|
81
|
+
private void Start()
|
82
|
+
{
|
83
|
+
this.rigidbody = this.GetComponent<Rigidbody>();
|
84
|
+
this.sphereCollider = this.GetComponent<SphereCollider>();
|
85
|
+
this.rigidbody.isKinematic = false; // 非キネマティックにする場合...
|
86
|
+
this.rigidbody.useGravity = false; // 重力を作用させなくする
|
87
|
+
}
|
88
|
+
|
89
|
+
private void Update()
|
90
|
+
{
|
91
|
+
var plane = new Plane(Vector3.up, this.rigidbody.position);
|
92
|
+
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
93
|
+
float rayDistance;
|
94
|
+
plane.Raycast(ray, out rayDistance);
|
95
|
+
if (rayDistance > 0.0f)
|
96
|
+
{
|
97
|
+
this.destination = ray.GetPoint(rayDistance);
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
private void FixedUpdate()
|
102
|
+
{
|
103
|
+
var velocity = this.rigidbody.velocity;
|
104
|
+
this.rigidbody.MovePosition(Vector3.SmoothDamp(this.rigidbody.position, this.destination, ref velocity, 1.0f, 10.0f, Time.fixedDeltaTime));
|
105
|
+
// 非キネマティックに変えたので、MovePositionによる位置操作の結果が自動的にrigidbody.velocityに
|
106
|
+
// 反映されなくなるため、更新されたvelocityをrigidbody.velocityに再代入してやる
|
107
|
+
this.rigidbody.velocity = velocity;
|
108
|
+
|
109
|
+
// 先に投稿したコードのtranslationをvelocityに置き換えると、得られる回転角は
|
110
|
+
// 1秒あたりの弧度法による回転量...つまり角速度の大きさとなる
|
111
|
+
// 回転軸も前回と同様の方法で求め、これが角速度ベクトルの向きとなる
|
112
|
+
// あとは求めた角速度ベクトル(向きaxis、大きさangularSpeed)を
|
113
|
+
// rigidbody.angularVelocityに代入すればいいはず
|
114
|
+
|
115
|
+
var speed = velocity.magnitude; // 速さ
|
116
|
+
var scaleXYZ = transform.lossyScale; // ワールド空間でのスケール推定値
|
117
|
+
var scale = Mathf.Max(scaleXYZ.x, scaleXYZ.y, scaleXYZ.z); // 各軸のうち最大のスケール
|
118
|
+
var angularSpeed = speed / (this.sphereCollider.radius * scale); // 角速度の大きさ
|
119
|
+
var axis = Vector3.Cross(Vector3.up, velocity).normalized; // 角速度の向き
|
120
|
+
this.rigidbody.angularVelocity = angularSpeed * axis;
|
121
|
+
}
|
122
|
+
}
|
123
|
+
```
|
1
球の半径がスケールを反映していなかったため修正
answer
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
あるフレームで球が`rigidbody.velocoty * Time.deltaTime`移動したとし、これを`translation`とします。
|
4
4
|
移動距離は`translation.magnitude`で、これを`distance`とします。
|
5
|
-
|
5
|
+
オブジェクトのスケールを`scale`とすると、コライダーの本来の半径が`sphereCollider.radius`ですので、球の半径は`this.sphereCollider.radius * scale`となり、弧度法による回転量は`distance / (this.sphereCollider.radius * scale)`となります。
|
6
6
|
|
7
7
|

|
8
8
|
|
@@ -38,10 +38,12 @@
|
|
38
38
|
{
|
39
39
|
this.destination = ray.GetPoint(rayDistance);
|
40
40
|
}
|
41
|
-
|
41
|
+
|
42
42
|
var translation = this.rigidbody.velocity * Time.deltaTime; // 位置の変化量
|
43
43
|
var distance = translation.magnitude; // 移動した距離
|
44
|
+
var scaleXYZ = transform.lossyScale; // ワールド空間でのスケール推定値
|
45
|
+
var scale = Mathf.Max(scaleXYZ.x, scaleXYZ.y, scaleXYZ.z); // 各軸のうち最大のスケール
|
44
|
-
var angle = distance / this.sphereCollider.radius; // 球が回転するべき量
|
46
|
+
var angle = distance / (this.sphereCollider.radius * scale); // 球が回転するべき量
|
45
47
|
var axis = Vector3.Cross(Vector3.up, translation).normalized; // 球が回転するべき軸
|
46
48
|
var deltaRotation = Quaternion.AngleAxis(angle * Mathf.Rad2Deg, axis); // 現在の回転に加えるべき回転
|
47
49
|
|