FPSキャラクター
課題
ファーストパーソン・シューティングゲーム(FPS)用のキャラクターを作成してください。
解決策
まず、CharacterBody3D ノードから始め、次に CollisionShape3D を追加してください。この場合、最も一般的な選択肢は CapsuleShape3D 衝突形状です。ワールドの設定によっては、ここに他の形状も追加できますが、この例では基本に忠実に進めます。
サイズはすべて初期設定値のままにします(カプセルの高さは2メートルとなります)。地面と底面を揃えるため、高さを1.0m移動させてください。
次に、ボディの子要素として Camera3D を追加し、約 1.6m 持ち上げてください。
この例では、「身体がない」状態、つまりプレイヤー用の表示メッシュを追加しないケースを考えます。環境によっては、プレイヤーの身体を表示する必要があるかどうかは異なるでしょう。
スクリプトをbodyにアタッチし、まずプロパティを定義することから始めてください。
extends CharacterBody3D
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
var speed = 5
var jump_speed = 5
var mouse_sensitivity = 0.002
_physics_process()関数は移動処理を担当する箇所です。注意すべき点として、Input.get_vector()関数は前進/後退/左右キーの組み合わせに基づいて2次元ベクトルを返します。このベクトルを利用して、ボディの速度におけるxおよびz成分を設定することになります(y方向は重力によって自動的に処理されるため)。このベクトルにボディのbasisを掛けることで、回転を考慮に入れつつ適切な方向に移動させることができます。つまり、前方は常に『ボディ自体』の前進ベクトルを指すようにするわけです。
func _physics_process(delta):
velocity.y += -gravity * delta
var input = Input.get_vector("left", "right", "forward", "back")
var movement_dir = transform.basis * Vector3(input.x, 0, input.y)
velocity.x = movement_dir.x * speed
velocity.z = movement_dir.z * speed
move_and_slide()
if is_on_floor() and Input.is_action_just_pressed("jump"):
velocity.y = jump_speed
入力マッピングに「W」「A」「S」「D」(標準設定)またはコントローラーの軸(好みに応じて選択可能)を使用して、適切な入力アクションを必ず追加してください。
以下の手順で「World」シーンにプレイヤーを追加してください。床にStaticBody3Dノードを、壁用に複数のノードを作成済みとします。
移動しようとすると、前後・左右に動けるものの、回転はできないことがわかります。次はこの点を処理していきます。
3D空間におけるマウス操作制御
まず、マウスを動かすのと同じ方向にプレイヤーを左/右に回転させる必要があります。マウス入力は画面座標系で2次元的に表現されるため、マウスの水平方向(x)の動きを、垂直軸であるyを軸にしたプレイヤー本体の回転に変換する必要があります。先ほど定義したmouse_sensitivityプロパティを使えば、マウス移動量がどれだけ回転角度に相当するかを調整できます。
func _input(event):
if event is InputEventMouseMotion:
rotate_y(-event.relative.x * mouse_sensitivity)
コードをもう一度実行してみると、マウスで回転操作ができるようになっていることが確認できるはずです。ただし、マウスカーソルがゲームウィンドウの外にはみ出してしまう場合があります。このタイミングで、マウスをキャプチャするコードを追加すると良いでしょう。詳細については入力:マウスのキャプチャをご覧ください。
更新されたコードは次のようになります。
func _input(event):
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
rotate_y(-event.relative.x * mouse_sensitivity)
最後に、上下移動にはマウスのyモーションを使ってカメラを傾けます。完全に逆さまになるのは避けたいので、回転値はclamp()で70度という合理的な範囲に制限します。
func _input(event):
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
rotate_y(-event.relative.x * mouse_sensitivity)
$Camera3D.rotate_x(-event.relative.y * mouse_sensitivity)
$Camera3D.rotation.x = clampf($Camera3D.rotation.x, -deg_to_rad(70), deg_to_rad(70))
武器の所持について
FPSキャラクターには通常、前面に位置した武器の3Dメッシュが用意されています。これをセットアップするのは、Godotエディターの便利な機能を使えば簡単に行えます。
武器モデルをCamera3Dの子要素として追加してください。その後、エディタービューメニューで「2つのビューポート」を選択し、そのうち1つをカメラプレビュー用に設定してください。これで、武器を自由に移動させながら、プレイヤー視点でどのように見えるかを簡単に確認できるようになります。
個性を加えるには、AnimationPlayer を使用して武器の位置をプレイヤーの移動に合わせて左右にアニメーションさせる方法がオススメです。
関連レシピ
プロジェクトのダウンロード
プロジェクトコードはこちらからダウンロードしてください。https://github.com/godotrecipes/basic_fps