俺に解るように説明する "Godot Engine 3.x" 入門+

ゲームエンジン Godot Engine に関すること。入門とか使い方とかチュートリアルとか、あれとかこれとか。日本語解説。

Godot GDScript 17 「Quat と slerp()」 2/2

Quat()でとってきて、Transform()であてはめる。」 前回やったコレこれさえ覚えておけば、物体Aが持ってる回転を物体Bに反映できる。今回はとってくるQuatslerp()させる。以下のGIFのように、角の小さい方を通ってミーターゲットと同じ方向を徐々に向くようになれば成功だ。

f:id:ore2wakaru:20180422154534g:plain

(ターゲットの方向を向くんじゃないからね。ターゲットと同じ方向を向くんだよ。)


C = A.slerp(B, t)

AからBへtの割合だけ近づけた値をCに入れる。0°(360°)をまたいで処理してくれる。それがslerp()。注意したいのは、A、B、CはQuat型。Vector3型やfloat型でslerp()したいって言っても出来ないからね。(GDScriptの16にある図を参照。)


ノードのプロパティ

は、ミーターゲットも好きにy軸で回転させたらいいよ。ちなみに上のGIFは

f:id:ore2wakaru:20180422172244p:plain

  • ミー: Rotation Degrees: "(0, 10, 0)"
  • ターゲット: Rotation Degrees: "(0, -60, 0)"

になってる。いろいろ値を変えてみるべし。


スクリプト1

slerp()させるのに、ほとんど変更なくできるのがすごいな、。ネットで見つけた情報より断然分かりやすい。さすがだな、うんうん。(だが、元情報がなければ手も足も出なかったんだけどな。それは内緒だ。)

f:id:ore2wakaru:20180422170739p:plain

L6

  • 自分(ミー)のQuat値を入れる変数を準備。

L9

  • 加速・減速でやったのと同じように、今回も、ここでtの値をセット。
  • "0.03"は3%ということ。つまり、slerp()で、与えられたABの差を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

f:id:ore2wakaru:20180421195628p:plain

基本3つ(入力時の変換候補の3パターン)あって、前回やったのと今回上のスクリプトでもやっているのは、"basis"でとってくる方法。(図の3番目)

だが、キャラコンに当てはめるには、これより図の2番目にある「 と 角度」で、Quat値をとってくる方が都合がよさそう。なぜなら、

  1. 具体的なノード(オブジェクト)が必要ない。
  2. anat2()で必要な角度はすでに取得している。
  3. はy軸に決まっている。

という事だからだ。

では、実際にスクリプトを変更して、「 と 角度」で、Quat値をとってこよう。

ターゲットはy軸で-60°だから、L17を、

f:id:ore2wakaru:20180422170723p:plain

とすればいい。

  • "Vector3(0, 1, 0)"はy軸を表す。
  • "-PI/3"は-60°だ。

簡単。もう具体的なノード(オブジェクト)である"Spatial_Target"は必要なくなった。L4L14はいらない。コメントアウトするなり、消すなりすればいい。

スクリプトを変更して、これも一番最初の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)