はじめに
Unity2021.2
以上からSourceGenerator
を利用することができるようになりました。
ソース ジェネレーターを使用すると、C# の開発者がコンパイル時にユーザー コードを検査できます。 ソース ジェネレーターは、ユーザーのコンパイルに追加される新しい C# のソース ファイルを即座に作成します。 この方法で、コードをコンパイル中に実行することができます。
ソース ジェネレーター - C# | Microsoft Learn
コンパイルをするときにC#
コードを自動生成することができる機能といったところでしょうか。
ソース ジェネレーター - C# | Microsoft Learn
またUnityにはILPostProcessor
というコンパイル後のIL
をいじれる機能があります。以下のブログのILPostProcessor
とSourceGenerator
の箇所が面白いので、よければ是非一読してみてください。
forpro.unity3d.jp
Unity公式でもILPostProcessor
からSourceGenerator
に移行している箇所もあるようです。(ただSourceGenerator
がILPostProcessor
の完全上位互換というわけではないので注意)
今後利用が増えていく可能性が高そうなので、SourceGenerator
を今のうちに学んでおくのも良さそうかもしれません。
対応環境
公式ドキュメントではUnity2021.3
からSourceGenerator
の記載があります。
docs.unity3d.com
自分の目で確かめたわけではないですが、おそらくUnity2021.3 or newer
かと。
実験環境
Rider2022.3.2
Unity2022.2.1f1
Source Generatorの実装
Source Generator
を実装にはUnity
を使うわけではなく、Visual Studio
等を利用します。私の場合はRider2022.3.2
を利用していきます。
最初に流れを書いておくと、以下のことをしていきます。
.NET Standard 2.0
のプロジェクト作成Microsoft.CodeAnalysis 3.8
のインストールISourceGenerator
を実装し、Generator
属性がついたクラスを作成- プロジェクトをビルド、
Dll
を出力
まず.NET Standard 2.0
向けのプロジェクトを作成します。ここで.NET Standard 2.0
以外のものを選ばないよう注意してください。
次にMicrosoft.CodeAnalysis 3.8
をプロジェクトにインストールします。
Rider
の場合はメニューバーよりTools -> NuGet -> Show NuGet Tool Window
を選択し、Microsoft.CodeAnalysis
を検索、v3.8
を選びインストールします。
次にISourceGenerator
を実装したクラスを作成し、Generator
属性をclass
につけます。
using Microsoft.CodeAnalysis; [Generator] public class SourceGeneratorSample : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { // Source Generatorを初期化するときに実行 // 例:元のソースコードからコード自動生成のためのコードを収拾するために ISyntaxReceiverを行う } public void Execute(GeneratorExecutionContext context) { // コード生成を行うときに実行 // 例:実際にコード生成のロジックを記述 } }
今回は動作するまでの手順の説明記事にしたいので、コードの説明はしません。(私自身もっと理解してからSourceGenerator
に関する細かい記事も書きたいです)
ひとまずUnity公式のサンプルを参考にしながら以下のようなコードを記述してみました。
using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Text; namespace SourceGeneratorTest { [Generator] public class SamplePropertyGenerator : ISourceGenerator { // SampleAttributeのコード本体 private const string AttributeText = @" using System; namespace Sample { [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] sealed class SampleAttribute : Attribute { public SampleAttribute() { } } } "; public void Execute(GeneratorExecutionContext context) { // hintName : 任意の一意の名前を指定する 名前には".g.cs" や ".generated.cs" などの明示的な C# ファイル拡張子を指定するのが一般的 // NOTE : https://learn.microsoft.com/ja-jp/dotnet/csharp/roslyn-sdk/source-generators-overview context.AddSource( hintName : "Sample.Generated.cs", sourceText: SourceText.From(AttributeText, Encoding.UTF8)); } public void Initialize(GeneratorInitializationContext context) { } } }
コードが書けたらビルドして、.dll
を出力します。
Unity側での設定
Unity側では以下の操作を行います。
.dll
のインポートAsset Labels
にRoslynAnalyzer
を設定
先程生成した.dll
をUnityへインポートします。
最後に.dll
を選択してインスペクターより、Asset Labels
にRoslynAnalyzer
を設定すれば完了です。
また公式ドキュメントではEditor
とStandalone
を設定してと記載されていますが、Select platforms for plugin
は選択しなくても動作するらしいです。
Unity 2022におけるC#ランタイムスクリプトについて – Unity for Pro
5. Go to Select platforms for plugin and disable Any Platform.
6. Go to Include Platforms and disable Editor and Standalone.
Roslyn analyzers and source generators - Unity マニュアル
以下のようなコードを書いてもエラーが出力されないので、Sample
属性が生成されていることが分かります。
public class Sample { [Sample] private int value; }
// RiderでGo to Declaration or Usagesで自動生成されたコードの中身を見れる using System; namespace Sample { [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] sealed class SampleAttribute : Attribute { public SampleAttribute() { } } }
しっかりとSourceGenerator
が動作していることが確認できました。