Godotでコンパスをつくる

FPSでよくあるやつ

制作中のゲームに、画面上部で横スクロールして方角を示すタイプのコンパスを実装したのでその記録を残しておきます。Webで作例を探そうと「ゲーム制作 コンパス」などのキーワードで検索しても関係ないページばかりヒットするので、全体の構成はChatGPTに訊いて調整が必要なところを人力で直しました。

前提

Godot4.4.1Stable
シェーダーを使用

概要

SubViewportを使ってコンテナに横一列で並べたラベルの見たままの画像を取得→シェーダーを使って無限ループしているように見せる

手順

シーン構造

新規シーンでCanvasLayerを作成
子ノードにTextureRectとSubViewportを追加
SubViewportの子にHBoxContainerを追加して、さらにその子にLabelを8つ(示したい方角の数だけ)追加

SubViewport側(ゲームには直接表示されない)

Disable3Dをオンに
LabelのTextにN、NE、E……とそれぞれ方角の文字を入力する
LabelのHorizontalAlignmentをCenterに設定
HBoxContainerのThemeOverridesからSeparationを0に設定
Labelの横幅はすべて90px、SubViewportとHBoxContainerの横幅は720pxに設定(好みに合わせて)

TextureRect側(実際に表示されるコンパス)

Textureに新規ViewportTextureでSubViewportを指定
ExpandModeをIgnoreSize、StretchModeをKeepCenteredに設定
ClipContentsをオン
横幅を180pxに設定(画面サイズに合わせて)
AnchorsPresetを中央上に設定
Materialに新規ShaderMaterialを追加して、適当な名前でシェーダーファイルを作成し以下のようにシェーダーコードを追加

shader_type canvas_item;

uniform float rotation_degrees = 0.0;

void fragment() {
	float scroll = -rotation_degrees / 360.0;
	vec2 uv = UV;
	uv.x = fract(uv.x + scroll + 0.5625); #後ろの数値は私の場合。要調整
	COLOR = texture(TEXTURE, uv);
}

スクリプト

親のCanvasLayerにスクリプトをアタッチして、以下のコードを追加

extends CanvasLayer

@onready var player := get_node("/Path/To/Player") #プレイヤーのノードを指定
@onready var compass_view := $TextureRect
var shader_material

func _ready() -> void:
	shader_material = compass_view.material as ShaderMaterial

func _process(delta: float) -> void:
	var yaw_rad = player.rotation.y
	var yaw_deg = fmod(rad_to_deg(yaw_rad), 360.0)
	
	shader_material.set_shader_parameter("rotation_degrees", yaw_deg)

これでプレイヤーの回転に合わせて方角を示す文字がスクロールする(はず)。
TextureRectに指定する画像はペイントソフトで作成してもいいですが、個人的には上のやり方が見た目シンプルでサイズ調整も手軽にできて好きです。装飾したいなら当然描く必要あり。

なんとなくこういう機能にシェーダーはあまり使いたくないなと思っていましたが、シェーダーを使わない方法は上手く画像をループさせられなかったので諦めました。

以上です
ここまでお読みいただきありがとうございました。
よろしければ購読をお願いします。

購読 Pixel&Voxel

最新の投稿を見逃さないように。サインアップするとメンバー限定記事へアクセスできます。
jamie@example.com
購読