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

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

Godot 玉転がし 11 「回収物 置く & 回転」

当初の予定通り、12個の回収物(コレクタブル)を置くことにしよう。さらに、見栄えを気にして、無駄に回転させるぞ。で、これは、スタティックでもなく、キネマティックでもなく、リジッドでもなく、エリア(「Area」ノード)で作る。理由は、
f:id:ore2wakaru:20180310193409p:plain

表面でコライドさせたくないから。動かしてる玉に、あえて「ゴッツンゴッツン」と動きを止める、ヒットストップ的な動きをさせるのは変だろ。「スーーッ」と通過してもらおうじゃないか。こっちの方がゲームとして自然だ。

マリオがコインを取るときに、いちいちゴッツンゴッツンしてたらヤダろ。そういうこと。


「Area」ノード 組み合わせ

使い方だが、スタティック、キネマティック、リジッドと同じだ。これ、本当に便利な組み合わせだな。
f:id:ore2wakaru:20180310194701p:plain
Area」ノードを親にして、「MeshInstance」ノードと「CollisionShape」ノードを子に持たせればいい。それぞれのカタチの設定はもうここでは書かないが、もちろん忘れずに行うこと。俺はキューブにしたけどな。

ちょっと注意。ここで使う「CollisionShape」は、コリジョンって書いてあるけど、表面衝突で「ゴツン」とはならないもの。あくまでもエリアに侵入したかどうかの判定で使用するもの。混乱するなかれ。


回転させる

スクリプトで回転させる。場所は、_process(delta)ばーちゃんファンクション内。_physics_process(delta)じゃない理由は、エリアは物理法則にしたがって、ぶつけたりぶつけられたりさせないから。ついでに、これはリジッドボディーでもないから、_integrate_forces(state)はあり得ない。

では、さっそく、コード。
f:id:ore2wakaru:20180310213232p:plain

  1. 回転速度を変数に入れる。1秒間に何度(角度)回すかということ。 ちょっとややこしいのが、角度は、度(°)ではなく、ラジアンでやること。それから、PIというのは、Godotが決めてある数(定数)で、読んでそのまま、π(パイ)のこと。3.14159...。ま、色が黄色くなってるからGodotが決めたもんだと分かるよね。
    ラジアンでいくと、PIは180度だろ。これを基準に考えればいいよな。コメントにも書いたけど、2PIは360度。当然、PI/2は90度。ってことで、ここでは、1秒間に90度回転させようって思って、変数を設定してある。
  2. global_rotate()は、
    global_rotate( 軸 , 角度 )
    と使う。「軸」はVector3型、「角度」はラジアン
    "global"ってあるんだから、回転軸がグローバル軸なのは明白だよね。"Vector3(0,1,0)"y軸を表すのも分かるだろう。(たぶん探せば、Godotの定数として何かあるんだと思うけど。)
    ちょっと難ありなのが、角度に"delta"を掛けている所。"my_turn * delta"秒角になる。掛けるの忘れるな。


いろんなコードをみると分かるけど、"delta"を掛けることで速度なら秒速に、角度なら秒角にしたりする。なぜか?
この、_process(delta)は1回の描画が終わったタイミングで呼ばれる。つまり世に言うFPSってやつだよ。イイPCなら200FPSでも、しょぼいPCなら50FPS、みたいになるよね。だから、PCの性能で呼ばれる回数が違ってくるのが当たり前になる。
でも、呼ばれる回数が違っても、キャラの移動速度やら回転速度を揃えなけりゃいけないだろ。PC毎に、動きが無茶苦茶にならないようにな。では、どうすればいいか? と考える。

1回に動かす量を変えればいいだろ。だろ。簡単。

イイPC(いっぱいココの関数が呼ばれる)なら1回の移動量・回転量を少なくする。しょぼいPC(あんまりココの関数が呼ばれない)なら、1回の移動量・回転量を多くする。考え方はこれでイイ。
で、"delta"との関係だが、この"delta"には、この関数が前回何秒前に呼ばれたかの時間情報が入っている。
仮に、200FPSだったら、"delta"に何が入る? 50FPSだったら? 考えてみ。
200FPSなら、「1 ÷ 200」で「0.005」。50FPSなら、「1 ÷ 50」で「0.02」。
もう感覚的に分かるよね。「0.005」を掛ければ、1回の移動量・回転量は少なくなるし、「0.02」なら、1回の移動量・回転量は多くなるだろ。比較の問題。
だが、1秒間に進む距離はどうか?
200FPSなら、「1 ÷ 200 × 200」で「1」、50FPSなら、「1 ÷ 50 × 50」で「1」。あたりまえだけど、同じ。
という風に、"delta"を掛けることで、移動量・回転量を揃えることが出来る。


本日の成果

ぐるぐる~。
f:id:ore2wakaru:20180310225814g:plain
あとは、[Ctrl]+[D]でいっぱい増やして適当に配置すればいいよね。


コピペ用

extends Area

var my_turn = PI / 2 # 2PIは360度、つまりPI/2は90度

func _process(delta):
    global_rotate(Vector3(0,1,0), my_turn * delta)