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

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

Godot キャラコン 03 「カメラぐるぐる 2/2」...縦

「横ぐるぐるが」出来たので、今度は縦にうなづけるようにする。じゃ~「縦うんうん」か。で、注意点としては、ノード自身が持っている軸(ローカル軸)で回すのと、回す際、際限なく回すのではなく、±80度などの限度をつけること。この2点に注意してスクリプトしていく。(本当は回してないんだけどね。)
f:id:ore2wakaru:20180330035022g:plain


うなづきスクリプト

先に貼るぜ。スクリプトの追加部分は2ヶ所な。丁寧な解説は以下。
f:id:ore2wakaru:20180330014215p:plain

[1]

var my_head_ang = 0.0             # head virtical angle
var my_head_ang_max = PI / 3.0    # head max virtical angle (60 deg)

1行目

  • ヘッドのうなづきアングルを入れる変数の設定。ヘッドの縦角度を入れ、上下に傾き過ぎないようチェックするためのもの。角度はラジアンで入る。
  • "0.0"とここで数値を入れているが、もっと安全にやりたかったら、_ready()関数内でヘッドのx軸の回転角度を入れるようにすればいい。ま、普通に置いた場合は"0"だから、こうしたケド。

2行目

  • ヘッドの傾き限界角の設定。さっきも注意点として挙げたけど、普通は縦方向に360度ぐるぐる回るようにはしないよね。カメラがひっくり返らないように、傾く限度を設ける。ラジアンで設定。
  • 今回は計算が楽なので、±60度内で動いてもらうよう、限度は60度に設定。前にも出て来たけど、PIはGodotが決めた値(定数)で180度を表すラジアンだったよね。3で割ってるから、角度的には60度ね。

[2]

    # virtical
    my_head_ang = my_head_ang - my_mou_rel.y * my_mou_sen
    my_head_ang = clamp(my_head_ang, -my_head_ang_max, my_head_ang_max)
    my_head.rotation.x = my_head_ang

1行目はコメント。virtical(発:バーティカル、意:垂直の、の)。ちなみにhorizontal(発:ホリゾンタル、意:水平の、の)。

2行目

  • マウスが縦方向に動いた分(my_mou_rel.y)、現状のヘッド角から減算。マウスセンシを掛け忘れるなよ。
  • 減算するか加算するかは、お好みで。フライトシミュみたいにしたかったら加算すれば。
  • 普通は、上下左右の操作を反転できるようにインバートの変数を設けるけど、今回はめんどいのでナシだ。

3行目

  • clamp()関数は便利すぎるから絶対覚えよう。ちなみに黄色いからGodotの内蔵関数って分かるよね。
clamp(変数, 下限, 上限)

のように指定して、変数の値が「下限~上限」の間から出ないようにしてくれる。ま、出ないようにというか、出たら、それぞれ上限値・下限値になるってこと。

  • 今回だったら、ヘッドのうなづきアングル("my_head_ang")は±60度に限定したいじゃん。でもマウスが動いた分、先にザックリ引いちゃってる。そうすると、場合によっては既に限度からはみ出してるかもだろ。だから、これを使って、はみ出した部分は無視してもらうってこと。
  • clamp(発:クランプ、意:締め金、~を留める)。締め金って何かよく分かんないけど、数値が「下限~上限」の中に留まるようにするってことだな、きっと。

4行目

  • ヘッドのうなづき角は±60度(もちろん変数はラジアンで入ってるぞ)になってる。それをヘッドのx軸に入れる。
  • "my_head.rotation.x"で、ヘッドのローカル軸xの数値を直接いじるぜ。さらっと言ってるけど、よく分からない時はAPIを確認してくれよな。Spatialくらすの変数。
    f:id:ore2wakaru:20180330031602p:plain
  • 関数を使って回すのではなく、数値を入れてる。せっかく数値を限ったんだから、ズバリそれをセットして使えばいいよね。グローバルで回しちゃダメだぜ。


確認

これで、横にも縦にも思い通り動くはず。シーン再生じゃ。

まだ、マウスカーソルがゲーム画面を出たらダメだけどな。


あー、今回コメントは、万一、外人さんがコードを見たとき分かりやすいかな~って思って英語にしてみたけど(コードの一部分だけコピペしてググると、俺のブログがヒットする場合があるからな~)、次回から日本語で書こうかな。間違った英語だったら、逆に意味不明だしな。

コピペ用

extends KinematicBody

# mouse
var my_mou_sen = 0.01           # mouse sensitivity
var my_mou_rel = Vector2(0, 0)  # mouse relative

# head (camera pivot)
var my_head                     # head node
var my_head_ang = 0.0           # head virtical angle
var my_head_ang_max = PI / 3.0  # head max virtical angle (60 deg)

func _ready():
    my_head = get_node("Spatial_Head")

func _input(event):
    if event is InputEventMouseMotion:
        my_mou_rel = event.relative

func _physics_process(delta):
    
    # head movement
    # horizontal
    my_head.global_rotate(Vector3(0, 1, 0), -my_mou_rel.x * my_mou_sen)
    # virtical
    my_head_ang = my_head_ang - my_mou_rel.y * my_mou_sen
    my_head_ang = clamp(my_head_ang, -my_head_ang_max, my_head_ang_max)
    my_head.rotation.x = my_head_ang
    # reset
    my_mou_rel = Vector2(0, 0)