2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Godot EngineのC#開発を加速!GodotOnReadyで効率的なコーディング

Posted at

目次

はじめに

はじめまして、ガルムと申します。
最近Unityでごたごたがあり、新しい技術に触れてみようと思いGodot Engineに立ち向かってみました。
今回はGodotEngineを使用するにあたり、GDScriptのいわゆる@onreadyに関してC#でも実現できないかと思い調査した結果を記述したいと思います。

onready とは?

本題に移る前にGDScriptの@onreadyに関して簡単に説明します。
Godot Engineではノードという概念が集まったシーンツリーというものがアクティブになることでゲームが起動します。

ここで以下のようなコードをノード内に書いたとしましょう。
(ここでの$LabelはUnityのいわゆるGetComponent("Label")と思ってください。)

var n = $Label

すると実行時エラーが出ます。
なぜなら、このクラスが初期化される時点ではまだLabelノードの実体がないためです。
シーンツリーは上から下に順に初期化されていくためです。

これ]]を解決するためにGDScriptには@onreadyが存在しています。
このキーワードをつけると、シーンツリー全体が初期化されたのちにLabelノードがnに代入されるようになります。

具体的には以下のように書きます。

@onready var n = $Label

こう書くことにより正しく動作させることができます。

具体的な説明は以下のサイトを参考にしてください。
https://worktoolsmith.com/godot-onready-keyword/

C#ではどうするか

Godot EngineではGDScript以外の言語を使用してゲームを開発することができます。
例えば、C#が挙げられますが、C#でノードを取得する場合には、以下のようにコードを書く必要があります。

private Label _label;

public override void _Ready()
{
    _label = GetNode<Label>("Label");
}

一つだけなら良いですが、複数取得するとなってくるとかなり面倒です。

GDScriptの@onreadyに相当するものは提供されていないのでしょうか?
調べてみると、同様の意見があるらしくissueが上がっていることに気が付きました。

どうやらGodot Engineは提供していないらしいです。
その代わりにSource Generatorを使用した、GodotOnReadyというOSSが公開されているようです。

GodotOnReady

実際に使用してみましょう

導入方法

NuGet packageにGodotOnReadyを追加することで使用できます。

.csprojが以下のようになっていれば成功です。

<Project Sdk="Godot.NET.Sdk/3.3.0">
  <PropertyGroup>
    <TargetFramework>net472</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="GodotOnReady" Version="1.2.4" />
  </ItemGroup>
</Project>

使用方法

メンバ変数に[OnReadyGet]アトリビュートをつけるだけです。

[OnReadyGet] private Label _label;

これは、以下と同じ動作をします。

private Label _label;

public override void _Ready()
{
    _label = GetNode<Label>("Label");
}

また、引数に"My/Button/Somewhere" といった文字列を渡すことで子以下のノードから取得することができます。

他にも[OnReady]といったアトリビュートがあります。
詳細は本家を読んでみてください。

内部動作

使用方法のみを説明してもつまらないので、内部でどのように動作しているかも見ていきたいと思います。
このOSSでは、Source Generatorが使用されています。
Source Generatorについての詳細は割愛しますが、いいかんじにコードを生成してくれるものだと思ってください。
Godot EngineでもC#を使用するときは内部的にSource Generatorが使われています。
興味がある方は調べてみてください。

さて、今回のOSSではどのようなコードが自動生成されるのでしょうか?
調べてみると、Parctial_XXX.csというファイルが生成されているようです。

using Godot;
using System;


partial class Player
{

    [Export] public NodePath SpritePath { get; set; }

    public override void _Ready()
    {
        base._Ready();

        if (SpritePath != null)
        {
            _sprite = GetNode<global::Godot.Sprite2D>(SpritePath);
        }
        if (_sprite == null)
        {
            throw new NullReferenceException($"'{((Resource)GetScript()).ResourcePath}' member '_sprite' is unexpectedly null in '{GetPath()}', '{this}'. Ensure 'SpritePath' is set correctly, or set OrNull = true in the attribute to allow null.");
        }
    }
}

/*
---- END OF GENERATED SOURCE TEXT ----
Roslyn doesn't clear the file when writing debug output for
EmitCompilerGeneratedFiles, so I'm writing this message to
make it more obvious what's going on when that happens.
*/

Godot Engineが提供している、_Ready()を使用してNodeを取得しているようです。

ただ、これだと、本来の_Ready()を使用することはできません。
メインのスクリプトでは以下のコードを使用することはできないのです。

public override void _Ready() 

そこで [OnReady] というアトリビュートが存在します。
詳しくは本家を参照してみて下さい。

さいごに

Godot EngineをC#使うにあたってGodotScriptのいわゆる@onreadyにあたるものがないかと調べてみました。
結果的にC#のOSSにあたるGodotOnReadyというもの発見しました。
よかったら使ってみてください。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?