Godot 玉転がし 09 「RigidBody Player Controller 2/2」
スクリプトを貼っ付けていこう。貼る場所はもちろん「RigidBody」ノード。リネームして"RigidBody_Player"にしたやつね。今回やる事が上手くいけば、WASDで、このGIFのように玉を動かせるようになる。
スクリプト
ズバリやるのが俺流。ということで、スクリプトを公開。詳しい解説付き。
extends
と、その後ろに書ける有効な文字列に関しては、ずっと前の記事にあるから、それ見て。- リジッドボディーを押す時の力の大きさを設定。適当に"20.0"としたが、この単位はキログラムなのか、ニュートンなのか、ジュールなのかは分からん。色々数値を変え、動かしてみて、自分的にシックリ行くのにすればいい。。。と思うがどうだろう。
- 前回紹介した、リジッドボディーを安全に動かせるタイミングを提供してくれるバーチャル関数。
-
キーワードの
if
は、if 条件: やりたいこと
みたいに書く。で、「条件」が「真(true)」のときに、「やりたいこと」の内容を実行する。大事なのは、「条件」の後ろにコロン「:」を書くことと、「やりたいこと」の前にインデント(TAB)を置く事。
この行では、Input Mapで設定したActionの、"my_left"が発生してるかを調べている。大事なのは、Aキーが押されているかではなく、(Aキーが押されたことによって)"my_left"という文字列が発生してるかを調べているところ。
発生しているかどうかは、Input
クラスのis_action_pressed()
を呼ぶことで分かる。()内には文字列を書く。ま、ここInput
クラスがいろんな入力データを握っていると考えればいい。発生していれば、true(真)を、発生してなければ、false(偽)を返す。 - 「条件」が「真」、つまり、
Input.is_action_pressed("my_left")
がtrueを返した時、ここが実行される。
add_force()
という関数を使ってリジッドボディーに力を加えるのだが、その前に、state.
を忘れずに書く事。このstate
はfunc _integrate_forces(state):
で書いたstate
のこと。こいつが、このスクリプトを貼ったリジッドボディーの状態を保持している。だから、書き忘れてはならない。
add_force()
は、add_force( 力の大きさ , 力を加える場所 )
のように書く。「力の大きさ」も「力を加える場所」も、どっちもVector3型で書く。
ここでは左に行きたいので、Vector3(-my_power, 0, 0)
と、x軸にはマイナスに力を働かせている。また、Vector3()
というのは、Vector3(0, 0, 0)
のこと。だから、物体のど真ん中に、-x軸方向の力を加えたことになる。 -
同様に、
"my_right"なら、+x軸方向に、
"my_up"なら、-z軸方向に、
"my_down"なら、+z軸方向に、
動くようにしているだけ。簡単。
このスクリプトを貼って、シーンの再生(又はゲームの再生)をしてみれば分かるが、このままでは、ちょっと問題もある。それは、、、次回解決。と思ったけど、やっぱ書いておこう。
スリープ(sleep)の解除とダンプの設定
[1] スリープ
実際にやってみると分かるが、急いでキー入力をして玉を動かさないと、その後一切のキー入力を発見してくれなくなるのだ。これは、リジッドボディーがスリープの状態に入ってしまうからだ。
シーンの再生後、玉はすぐに上から落ちてくる。ゴン。そして動かなくなる。ピタッ。そのまま、しばらくじっと見てると、Godotは「これ、止まったな。」と判断する。「これ、止まったな。」と思ったら、Godotは以後その物体に対して物理演算をしなくなってしまうのだ。この状態がスリープだ。
物理演算っていうのは、動いてないものに対して行うのはパワーの無駄遣いでしかないので、止まったと判断した物体には行わない。演算を行わないので、_integrate_forces(state):
関数は呼ばれなくなる。よって、このバーチャル関数の中に書いた処理はなされない。
つまり今回は、_integrate_forces(state):
関数内でAction(キー入力)データのチェックをしてるから、スリープ状態になると、キー入力のチェックはしなくなると言うわけ。
で、この解決方法なんだが、色々あるが、リジッドボディーがスリープしないようにしちゃうってのが、一番手っ取り早い。場所はココ。
チェックを外そう。これでリジッドボディーがスリープしなくなる。
何百個、何千個もスリープさせないようにするのは流石にどうかと思うが、1個だけだからね、今回は。これで解決としよう。
[2] ダンプ
これで玉は動くが、ちょこっとキーを押すと、その後も動きっぱなしで止まらない感じではなかろうか? ということで、ココをいじる。
"damp"ってのは「弱める」ってことらしい。"-1"の時は何もしないってこと。"0"超~"1"以下で、弱める強さを設定できる感じだ。俺は、"0.9"を入れたので、結構な強さで弱めている感じだ。「強さで弱める」とか、意味不明かもしれないが、数字がデカければ早く止まるってことね。ま、いろいろ数字を入れて試してみて。
ちなみに、今回は、"Linear"の"Damp"を設定して、移動の速度を減じたが、この下の項目、"Angular"の"Damp"だと、回転を減じることが出来る。
それから、最後に、玉が落ちてくるスピード、遅くなったはず。これは下方向に動くときもダンプが効いてるから、重力が弱められた感じになってしまう。
これがイヤなら、_integrate_forces(state):
の中身にx軸方向とz軸方向だけ弱めるコードを書けばいいんだけど、でもまー、今回はこれで。
コードのコピペ用
extends RigidBody var my_power = 20.0 func _integrate_forces(state): if Input.is_action_pressed("my_left"): state.add_force(Vector3(-my_power, 0, 0), Vector3()) if Input.is_action_pressed("my_right"): state.add_force(Vector3(my_power, 0, 0), Vector3()) if Input.is_action_pressed("my_up"): state.add_force(Vector3(0, 0, -my_power), Vector3()) if Input.is_action_pressed("my_down"): state.add_force(Vector3(0, 0, my_power), Vector3())