Godot GDScript 17 「Quat と slerp()」 2/2
「Quat()
でとってきて、Transform()
であてはめる。」 前回やったコレこれさえ覚えておけば、物体Aが持ってる回転を物体Bに反映できる。今回はとってくるQuat
をslerp()
させる。以下のGIFのように、角の小さい方を通ってミーがターゲットと同じ方向を徐々に向くようになれば成功だ。
(ターゲットの方向を向くんじゃないからね。ターゲットと同じ方向を向くんだよ。)
C = A.slerp(B, t)
AからBへtの割合だけ近づけた値をCに入れる。0°(360°)をまたいで処理してくれる。それがslerp()
。注意したいのは、A、B、CはQuat
型。Vector3
型やfloat
型でslerp()
したいって言っても出来ないからね。(GDScriptの16にある図を参照。)
ノードのプロパティ
は、ミーもターゲットも好きにy軸で回転させたらいいよ。ちなみに上のGIFは
- ミー: Rotation Degrees: "(0, 10, 0)"
- ターゲット: Rotation Degrees: "(0, -60, 0)"
になってる。いろいろ値を変えてみるべし。
スクリプト1
slerp()
させるのに、ほとんど変更なくできるのがすごいな、俺。ネットで見つけた情報より断然分かりやすい。さすが俺だな、うんうん。(だが、元情報がなければ手も足も出なかったんだけどな。それは内緒だ。)
L6
- 自分(ミー)の
Quat
値を入れる変数を準備。
L9
- 加速・減速でやったのと同じように、今回も、ここでtの値をセット。
- "0.03"は3%ということ。つまり、
slerp()
で、与えられたA~Bの差を3%づつ近づけようって事。 - ただ、今回は
_process(delta)
で回してるから、PC性能で近づくスピードは全く異なるから注意。あれだったら、そこを物理プロセス(_physics_process(delta)
)にすればいいよ。
L16
- 自分(ミー)の
Quat
値を入れる。 - これが回転のスタート値。
L21
- まんま、"C = A.slerp(B, t)"。
- スタート値であるA: "quat_me"から、ゴール値であるB: "quat_target"に、割合t: "my_acl"だけ近づけた値を、再度C: "quat_me"に入れている。コレ(C)が次のスタート値(A)になる。
- これで結局、"quat_me"は"quat_target"に限りなく近づく。もちろん
linear_interpolate()
同様、スタート値とゴール値は(四捨五入で同じになるかもだが)同じ値にはならない。論理上は限りなく近づくだけ。 - AもBも
Quat
型が見えてるからすげー分かりやすいな。俺天才。
L23
- 回転値のセットは
slerp()
させた"quat_me"で行う。 - ま、回転させると言うよりは、値の決め打ちで回転をセットするって感じだな。「何度回れ」的な処理ではなく、「何度になれ」という処理。
これで、一番最初のGIFのようになれば成功。ま、なるけどな。
Quat
のとってき方2
基本3つ(入力時の変換候補の3パターン)あって、前回やったのと今回上のスクリプトでもやっているのは、"basis"でとってくる方法。(図の3番目)
だが、キャラコンに当てはめるには、これより図の2番目にある「軸 と 角度」で、Quat
値をとってくる方が都合がよさそう。なぜなら、
- 具体的なノード(オブジェクト)が必要ない。
anat2()
で必要な角度はすでに取得している。- 軸はy軸に決まっている。
という事だからだ。
では、実際にスクリプトを変更して、「軸 と 角度」で、Quat
値をとってこよう。
ターゲットはy軸で-60°だから、L17を、
とすればいい。
- "Vector3(0, 1, 0)"はy軸を表す。
- "-PI/3"は-60°だ。
簡単。もう具体的なノード(オブジェクト)である"Spatial_Target"は必要なくなった。L4とL14はいらない。コメントアウトするなり、消すなりすればいい。
スクリプトを変更して、これも一番最初のGIFのようになれば成功。ま、これもなるけどな。
次回
「おばさん(33)」に、移動方向にスムーズに向いてもらう。
スクリプト1 "basis"でQuat()
extends Node var node_me #Spatial_Meノード操作用変数 var node_target #Spatial_Targetノード操作用変数 var quat_me #Spatial_MeのQuat値を入れる変数 var quat_target #Spatial_TargetのQuat値を入れる変数 var my_acl = 0.03 #C = A.slerp(B, t)のtの値 func _ready(): #ノードセット node_me = get_node("Spatial_Me") node_target = get_node("Spatial_Target") #Quatセット quat_me = Quat(node_me.global_transform.basis) quat_target = Quat(node_target.global_transform.basis) func _process(delta): #quat_meからquat_targetへslerp quat_me = quat_me.slerp(quat_target, my_acl) #node_me(Spatial_Meノード)の回転をセット node_me.global_transform = Transform(quat_me)
スクリプト2 軸、角度でQuat()
extends Node var node_me #Spatial_Meノード操作用変数 #var node_target #Spatial_Targetノード操作用変数 var quat_me #Spatial_MeのQuat値を入れる変数 var quat_target #Spatial_TargetのQuat値を入れる変数 var my_acl = 0.03 #C = A.slerp(B, t)のtの値 func _ready(): #ノードセット node_me = get_node("Spatial_Me") #node_target = get_node("Spatial_Target") #Quatセット quat_me = Quat(node_me.global_transform.basis) quat_target = Quat(Vector3(0, 1, 0), -PI/3) func _process(delta): #quat_meからquat_targetへslerp quat_me = quat_me.slerp(quat_target, my_acl) #node_me(Spatial_Meノード)の回転をセット node_me.global_transform = Transform(quat_me)