PONOS Advent Calendar 2023の25日目の記事です。
はじめに
先日は初めてUnityエンジニアがGodot Engineを触ってみたわけですが、
今回はチュートリアルを覗きながら引き続き触ってみました。
日本語のドキュメントも充実していますので、お勉強するに困らないですよね。
テスト環境
以下の環境やバージョンでテストしました。
- MacBook Pro (13インチ, 2020, Thunderbolt 3ポート x 4)
- macOS Monterey (バージョン 12.5.1)
- Godot Engine 4.2
デモプロジェクト
お役に立つデモプロジェクトが沢山あります。
- Godot demo projects
- Pong
その中でPongゲームに決定!
プロジェクトのインポート
Godot Engineを起動しましょう。
-
Pong with C#ページからプロジェクトをダウンロードします。
プロジェクトの実行
早速プロジェクトを動かしてみたいのですが…
- 実行するボタンを押したところ…ビルド時にエラーが発生!
どうやらGodot Engineの内製のC#エディターはバージョンが古いようですね… - Visual Studio Codeと連携しましょうか。
- 外部エディタの設定
- トップバーのメニューから「エディター→エディター設定」を開きます。
- .NETの外部エディターをVisual Studio Codeに設定し、再起動します。
- 改めて実行してみます。
エラーを一つずつ解決していきましょう。
エラーの修正
- なんと_Processのパラメーターがfloatからdoubleに変わったみたいですね…
- float型にキャストして、エラーを解消します。
// エラーログ
CS0266: 型 'double' を 'float' に暗黙的に変換できません。
// Godot 3.5
public override void _Process(float delta)
// Godot 4.2 - Ball.csの修正
public override void _Process(double delta)
{
var fDelta = (float)delta;
_speed += (fDelta * 2);
Position += _speed * fDelta * direction;
}
// Godot 4.2 - Paddle.csの修正
public override void _Process(double delta)
{
var fDelta = (float)delta;
position += new Vector2(0, input * MoveSpeed * fDelta);
}
- 変なエラーに遭遇したと思ったら、アクセス可能な拡張メソッドが大文字になっていました(罠)
- 大文字に修正することで解消できます。
// エラーログ
CS1061: 'Vector2' に 'y' の定義が含まれておらず、型 'Vector2' の最初の引数を受け付けるアクセス可能な拡張メソッド 'y' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足していないことを確認してください
// Vector2のプロパティを小文字から大文字に修正
public override void _Process(double delta)
{
var fDelta = (float)delta;
// Move up and down based on input.
float input = Input.GetActionStrength(_down) - Input.GetActionStrength(_up);
Vector2 position = Position; // Required so that we can modify position.y.
position += new Vector2(0, input * MoveSpeed * fDelta);
position.Y = Mathf.Clamp(position.Y, 16, GetViewportRect().Size.Y - 16);
Position = position;
}
- また文字列のToLower()で訳のわからないエラーが発生。
- おそらく親クラスであるNodeのNameプロパティの扱いが変わったと思いますが
- 今回は別の方法で回避しましょう。
// エラーログ
CS7036: 'MemoryExtensions.ToLower(ReadOnlySpan<char>, Span<char>, CultureInfo?)' の必要な仮パラメーター 'destination' に対応する特定の引数がありません
// 左右パドル名をインスペクターから設定できるようにする。
[Export]
private string _name;
public override void _Ready()
{
// エラーになるコード
string name = Name.ToLower();
// 修正したコード
string name = _name;
- 上記のコードに記述したようにフィールドに[Export]属性を付けることができます。
これで左右パドルを動かす準備ができました。
Inputについて
- パドルを動かす前に以下のページも一読し、より深く理解しましょう。
- インプットマップは「プロジェクト→プロジェクト設定ウィンドウ」を開くことで確認できます。
- 左パドルは「left_move_down, left_move_up」キーで動かします。
- 右パドルは「right_move_down, right_move_up」キーで動かします。
- パドルのスクリプトはこちら↓
// Input.GetActionStrength() メソッドを使って上下の入力を判定します。
float input = Input.GetActionStrength(_down) - Input.GetActionStrength(_up);
Inputの情報についてわかりました。
Area2D
- Pong ゲームは「ボール・天井・床・パドル・壁」で構成されていて、ボールと衝突することでインタラクションが発生します。
- その衝突処理をするために全てのオブジェクトはArea2Dを継承しています。
- Area2Dは、2D空間の領域を定義していて、他のCollisionObject2D ノードが進入、オーバラップ、および退出することを検出できます。
- UnityだとOnCollisionEnter2D, OnCollisionStay2D, OnCollisionExit2Dのことでしょう。
- 詳しくはこちらの一読をおすすめ。
- スクリプトに書いてメソッドと「接続・切断」することで衝突時の処理を制御できます。
- ノードのタブからシグナルの一覧が確認できますので、自由に設定しましょう。
- スクリプトの振る舞いに沿って命名し、Area2Dのシグナルと接続すれば衝突した時に呼ばれるはずです。
衝突処理の実装
- パドルはボールと衝突した時に反対側に飛ばします。
- バリエーションのため、Yの方向はランダムに!
public void OnAreaEntered(Area2D area)
{
if (area is Ball ball)
{
// Assign new direction
ball.direction = new Vector2(_ballDir, ((float)new Random().NextDouble()) * 2 - 1).Normalized();
}
}
- 天井と床はボールと衝突した時に反転の方向に飛ばします。
public void OnAreaEntered(Area2D area)
{
if (area is Ball ball)
{
ball.direction = (ball.direction + new Vector2(0, _bounceDirection)).Normalized();
}
}
- 壁と衝突したら、最初の位置に設定します。
public void OnWallAreaEntered(Area2D area)
{
if (area is Ball ball)
{
// Ball went off the side of the screen, reset it.
ball.Reset();
}
}
スクリプトの内容は少ないですが、これでも立派なゲームとして動作します。
スコアの加算やエフェクトとゲームオーバーまで入れると最高ですよね!
プレイしてみる!
最後に
プロジェクトを動かしてみながら、より広く勉強することができました。
やっぱりバージョンアップは簡単ではないですよね〜(最新バージョンでデモがコケたらユーザーは離れてしまうし)
エンジンの方がどんどん進化していっても、チュートリアルが追いついてこないことがよくありますよね。
でもプロジェクトのインポートから外部エディタの設定、Export属性とInput機能、Area2Dの衝突処理まで触ってみることで、Godot Engineの知識が増えた実感がします。
エディタが軽いのがお気に入りかもと。
今後ともGodot Engineの活躍を応援しながら見守ってみようかと思います。
さて、本日をもって PONOS Advent Calendar 2023 もおしまいです。
ここまでご覧いただいた方、誠にありがとうございました。