1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SerializeField と null 許容参照型の問題を解決したらボーナスがあった

Posted at

※ お金のボーナスの話じゃないです。

問題: SerializeField と null 許容参照型

Unity で null 許容参照型を有効にしている環境で、SerializeField に対して null 免除演算子を使っていたらレビューコメントがつきました。

[SerializeField] GameObject Target = null!;

void Awake()
{
    Assert.IsNotNull(Target);
}

null 免除演算子を使うことがいけないらしいです。個人的にはアプリケーション境界なのでアサーションして非 null として扱うのが妥当だと思ってコーディングしてました。こうすると参照設定が必須であることが宣言時にわかりますね。

ありがちな対応: フィールドを nullable にする

しょうがないのて nullable に変えました。

[SerializeField] GameObject? Target;

void Foo()
{
    Assert.IsNotNull(Target);
    Debug.Log(Target.name);
}

これなら文句はないでしょう。しかし参照設定エラーが、機能の実行時に発覚するのでは遅いですね。

改善: Required 属性 + ソースジェネレーター

Awake のアサーションはあったほうがいいですよね。nullable にするだけの変更が気に入らなかったので改善してやりました。つまり Awake のアサーションをソースジェネレーター化しました。

partial class FooBar
{
    [Required, SerializeField] GameObject? Target;
}

上のように書くと次のコードを生成します。

partial class FooBar
{
    void Awake()
    {
        AssertRequiredFields();
    }

    void AssertRequiredFields()
    {
        Assert.IsNotNull(Target);
    }
}

Required 属性をみつけて、それが MonoBehaviour の派生型なら Awake と AssertRequiredFields の定義を追加します。

ここで Required は自作の属性でタグとしてだけ機能します。

面倒な Awake の記述を省略できました! ユーザーが Awake メソッドを定義している場合は Awake の定義を省略します。その場合は AssertRequiredFields を使ってアサーションします。

ボーナス: 参照設定をビルド時に保証できるようになった話

という機能だったんですが、Required 属性を作ったのでもっと何かできないかと AI ちゃんと相談してました。すると「ビルド時に参照の設定を保証する」という機能が手に入りました。Unity を使うのは数年ぶりですが、昔に欲しいと思っていた機能が思いがけず手に入りました。AI すごいですね。

ところでアセットストアの Odin でもできるかもしれません。予算がでるところなら買って解決していいと思います。DDD でいうところの一般的な業務領域ですね。

AI エージェントにプロンプトすれば AI ちゃんが実装してくれるのでコードは省略します。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?